home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 21 / Cream of the Crop 21 (Terry Blount) (October 1996).iso / program / oxcc1434.zip / SRC / OXCCB.C < prev    next >
C/C++ Source or Header  |  1996-09-03  |  198KB  |  9,115 lines

  1. /*
  2.     oxccb.c -- v1.430 architecture neutral format (anf) to bytecode generator
  3.  
  4.     Copyright (c) 1995
  5.     Norman D. Culver dba
  6.     Oxbow Software
  7.     1323 S.E. 17th Street #662
  8.     Ft. Lauderdale, FL 33316
  9.     (954) 463-4754
  10.     ndc@icanect.net
  11.     All rights reserved.
  12.  
  13.  * Redistribution and use in source and binary forms are permitted
  14.  * provided that: (1) source distributions retain this entire copyright
  15.  * notice and comment, and (2) distributions including binaries display
  16.  * the following acknowledgement:  ``This product includes software
  17.  * developed by Norman D. Culver dba Oxbow Software''
  18.  * in the documentation or other materials provided with the distribution
  19.  * and in all advertising materials mentioning features or use of this
  20.  * software.
  21.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  22.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  23.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  24.  
  25. */
  26. #define MAJOR_VERSION 1
  27. #define MINOR_VERSION 433
  28.  
  29. void oxcc_debug();
  30. int __builtin_iv();
  31. void bterpdebug(void);
  32.  
  33. #include <stdlib.h>
  34. #include <string.h>
  35. #include <stdio.h>
  36. #include <setjmp.h>
  37. #include <time.h>
  38.  
  39. #define SUPPORT_LONG_DOUBLE 1
  40. #define SUPPORT_LONG_LONG 1
  41.  
  42. #define NEED_SPELLING 1
  43. #define NEED_BYTECODES 1
  44. #define NEED_AOUT_FORMAT 1
  45. #include "oxbytes.h"
  46.  
  47. #define NEED_FUNCTHUNK 1
  48. #define NEED_ANFDEFS 1
  49. #include "oxanf.h"
  50.     
  51. #define PROG oxccb
  52. #define USING_FRAMEWORK 1
  53. #define HOST_IS_LITTLE_ENDIAN 1
  54. #define REALLY_NEED_OFFSETS 1
  55. #define FUNCDATA (iv->category+1)
  56.  
  57. #define VFPRINTF(a,b) vfprintf(stderr,a,b)
  58. #define PERROR prerror
  59. #define PWARN prwarn
  60. #define PRINTF info
  61. static void prerror(const char *, ...);
  62. static void prwarn(const char *, ...);
  63. static void info(const char *, ...);
  64. int cfeprintf(const char *, ...);
  65.  
  66. #define FILEWRITE(buf, cnt)\
  67. {if(!iv->errors){if(fwrite(buf, 1, cnt, iv->outfile) != cnt)iv->errors = 12;}}
  68.  
  69. #define ROUNDING(a,b) ((a+(b-1))&~(b-1))
  70. #define ROUNDUP(a,b) a += ROUNDING(a,b)
  71.  
  72. #define KEYEQ(a,b) ((a)[0] == (b)[0] && (a)[1] == (b)[1])
  73. #define KEYLT(a,b) (((a)[1] < (b)[1]) || ((a)[1] == (b)[1] && (a)[0] < (b)[0]))
  74. #define MIN(a,b) (((a) < (b)) ? (a) : (b))
  75.  
  76. /* ======================== CONCATENIZATION MACROS ==================== */
  77.  
  78. #define    _cat2_(a, b)    a##b
  79. #define _cat_(a, b)    _cat2_(a, b)
  80. #define Global(a) _cat_(PROG, a)
  81.  
  82. #define _pname2_(x)    #x
  83. #define _pname1_(x)    _pname2_(x)
  84. #define pName        _pname1_(PROG)
  85.  
  86.  
  87. /* ============== ENDIAN MACROS (input format is litle endian) ==== */
  88.  
  89. #if HOST_IS_LITTLE_ENDIAN
  90. #define GL(a) a
  91. #define GS(a) a
  92. #define PL(a) a
  93. #define PS(a) a
  94. #else
  95. #endif
  96.  
  97. /* =================== INPUT DATA FORMATS ========================== */
  98.  
  99. #define INFILE_SYMNUM 1
  100. #define OUTFILE_SYMNUM 2
  101.  
  102. static unsigned char binops[] = {0,0,
  103. ADD,SUB,MUL,DIV,LSH,RSH,MOD,OR,XOR,AND,EQ,NE,LT,GT,LE,GE,
  104. NEG,COMP,NOT
  105. };
  106. /* ====================== STRUCTURES AND TYPEDEFS ======================== */
  107. typedef struct _jl {
  108.     struct _jl *next;
  109.     void *p;
  110.     char *q;
  111.     long *plabelval;
  112.     long offset;
  113. } *PJL;
  114.  
  115. typedef struct _el {
  116.     struct _el *next;
  117.     long spot;
  118.     short symnum;
  119. } *PEL;
  120.  
  121. typedef struct _afile {
  122.     unsigned char *file_p;
  123.     PopI header_p;
  124.     PopI size_p;
  125.     unsigned char *symtext_p;
  126.     unsigned char *prog_p;
  127.     unsigned char *data_p;
  128.     unsigned char *switch_p;
  129.     unsigned char *decl_p;
  130.     unsigned char *maxtemp_p;
  131.     unsigned char *seg_p;
  132.     unsigned char **symaddr;
  133.     unsigned char **decladdr;
  134.     unsigned long thunk_offset;
  135.     unsigned long bss_offset;
  136.     int maxtemp;
  137.     int maxtempclass;
  138.     void *datatbl;
  139.     short *symtran;
  140.     unsigned short *decltran;
  141.     int filenum;
  142.     int numsyms;
  143.     int numdecls;
  144.     int numrelocs;
  145.     int numsegs;
  146. } *Pafile;
  147.  
  148. typedef struct _iv {
  149.     int category;
  150.     FILE *outfile;
  151.     struct exec *header;
  152.     unsigned char **symaddr;
  153.     unsigned char **decladdr;
  154.     int remove_infile;
  155.     int argc;
  156.     char **argv;
  157.     int numfiles;
  158.     int lastlabel;
  159.     int errors;
  160.     int numsyms;
  161.     int numdecls;
  162.     int numsegs;
  163.     int maxtemp;
  164.     int maxtempclass;
  165.     unsigned long total_size;
  166.     unsigned long thunk_offset;
  167.     unsigned long bss_offset;
  168.  
  169.     struct _nodeO *ob_usedhead;
  170.     struct _nodeO *ob_usedtail;
  171.     struct _nodeO *ob;
  172.     unsigned char *ob_buf;
  173.     int ob_bufcnt;
  174.     struct _nodeO *first_ob;
  175.  
  176.     struct _nodeC *cod_usedhead;
  177.     struct _nodeC *cod_usedtail;
  178.     struct _nodeC *cod;
  179.     unsigned char *cod_buf;
  180.     int cod_bufcnt;
  181.     struct _nodeC *first_cod;
  182.     struct _nodeC *regcode;
  183.  
  184.     long first_temp;
  185.     long killop;
  186.     long stackdepth;
  187.     long maxdepth;
  188.     long mindepth;
  189.     long numnested;
  190.     long lastline;
  191.     void *reloctbl;
  192.     void *extrntbl;
  193.     void *gbltbl;
  194.     void *symtbl;
  195.     void *labeltbl;
  196.     void *newlabeltbl;
  197.     void *tmptbl;
  198.     void *segtbl;
  199.     void *functbl;
  200.     void *finalsymtbl;
  201.     void *finalstringpack;
  202.     long finalpacksize;
  203.     void *datatbl;
  204.     void *builtintbl;
  205.     int in_builtin;
  206.     int has_structret;
  207.     int temps_written;
  208.     unsigned char *obuf;
  209.     unsigned char *obufstart;
  210.     PEL extbuf;
  211.     void *extbufstart;
  212.     int extcnt;
  213.     int extbufcnt;
  214.     PEL finextbuf;
  215.     void *finextbufstart;
  216.     int finextcnt;
  217.     int finextbufcnt;
  218.     PJL jbuf;
  219.     void *jbufstart;
  220.     int jmpcnt;
  221.     int jbufcnt;
  222.     long obufcnt;
  223.     long out_offset;
  224.     long func_offset;
  225.     int extmark;
  226.     short markedsym[10];
  227.     char *markedbuf[10];
  228.     int filenum;
  229.     Pafile files[1024];
  230.     char debug;
  231.     char only_debug;
  232.     char strip;
  233.     char listing_wanted;
  234. } *Piv;
  235.  
  236. struct _gloval {
  237.     char *symname;
  238.     int symnum;
  239.     unsigned char *p;
  240.     Pafile pf;
  241. };
  242. struct _rkey {/* key area of reloctbl node */
  243.     unsigned long spot;
  244.     short fileno;
  245.     unsigned char opcode;
  246.     char rsize;
  247. };
  248. struct _rval {/* value area of reloctbl node */
  249.     unsigned char *p;
  250.     unsigned long *base;
  251.     long offset;
  252.     short rsym;
  253. };
  254.  
  255.  
  256. /* Internal User API */
  257. static void *Cmalloc(int category, unsigned amount);
  258. static void *Ccalloc(int category, unsigned nelems, unsigned elemsize);
  259. static void *Crealloc(int category, void* buf, unsigned newsize);
  260. static void Cfree(int category, void* buf);
  261. static void Cfreecat(int category);
  262. static int Cmemrange(int category, unsigned* minp, unsigned* maxp);
  263. static int Cusedrange(int category, unsigned* minp, unsigned* maxp);
  264. static void Ctotrange(unsigned* minp,unsigned* maxp);
  265. static int Cnewcat(void);
  266. static void Cguard(int category);
  267. static void* NewSymTable(int category, int nbins);
  268. static int SymFind(void *tbl, void *key, void *result);
  269. static int SymFindRange(void *tbl, void *key, void *result);
  270. static void *SymInsert(void *tbl, void *key, void *value, int datsiz);
  271. static int StringInsert(void *tbl, char *string, void *result);
  272. static int StringFind(void *tbl, char *string, void *result);
  273. static void SymDelete(void *tbl, void *key);
  274. static int SymHead(void *tbl);
  275. static int SymNext(void *tbl);
  276. static void SymGetMark(void *tbl, void *markptr);
  277. static int SymMarkNext(void *tbl, void *mark);
  278. static void SymSetMark(void *tbl, void *markptr);
  279. static void SymKey(void *tbl, void *keyptr);
  280. static void SymValue(void *tbl, void *datptr);
  281. static void *seg_find(Piv iv, int id);
  282. static char *filenameof(char *path);
  283. static char *propernameof(Piv iv, char *name);
  284.  
  285. /* END: User API */
  286.  
  287. /* ====================== PUT UNIQUE CODE HERE ========================= */
  288. static void newlabel_insert(Piv iv, long label);
  289. static long newlabel_fix(Piv iv, long label);
  290. static void *do_stmt(Piv iv, unsigned char *p);
  291. static void *do_expr(Piv iv, unsigned char *p);
  292. static void do_bracket(Piv iv, unsigned char *p, unsigned char *q);
  293. static void *do_something(Piv iv, unsigned char *p);
  294. extern char *ctime();
  295.  
  296. /* ===================== BYTECODE OUTPUT GENERATOR ======================= */
  297. struct _nodeOBUF
  298. {
  299.     struct _nodeOBUF *next;
  300.     long cnt;
  301.     char buf[1];
  302. };
  303. typedef struct _nodeC
  304. {
  305.     struct _nodeC *next;
  306.     struct _nodeOBUF *ee;
  307. } NODEC, *PNODEC;
  308.  
  309. typedef struct _nodeO
  310. {
  311.     struct _nodeO *next;
  312.     unsigned char *p;
  313.     ND d;
  314.     ND l;
  315.     ND r;
  316.     PNODEC startinst;
  317.     PNODEC endinst;
  318. } NODEO, *PNODEO;
  319.  
  320. static unsigned char get_datasize(unsigned char, PND);
  321. static void link_cod(Piv);
  322.  
  323. static char *notice = 
  324.     "  Generated by Oxbow Software Bytecode Backend version %d.%d\n*/\n\n";
  325.  
  326. static struct _nd longtype =         {D_SIGNED,0,B4,0,4,0,0};
  327. static struct _nd longlongtype =     {D_SIGNED,0,B8,0,8,0,0};
  328. static char padit[8];    /* in bss */
  329.  
  330. void
  331. bterpdebug(){}
  332.  
  333. static long
  334. symnumof(Piv iv, char *symb)
  335. {
  336. struct _gloval *valp;
  337.  
  338.     if(StringFind(iv->gbltbl, symb, &valp))
  339.         return (long)valp->pf->symtran[valp->symnum];
  340.     return 0;
  341. }
  342. static void
  343. buildin(Piv iv, char *symb, unsigned char code)
  344. {
  345. long key[2];
  346.  
  347.     if((key[0] = symnumof(iv, symb)))
  348.     {
  349.         key[1] = 0;
  350.         SymInsert(iv->builtintbl, key, &code, 1);
  351.     }
  352. }
  353. static void
  354. install_builtins(Piv iv)
  355. {/* USE THIS TO INSTALL WHATEVER BUILTINS ARE IN THE TARGET INTERPRETER */
  356. #define BUILDIN(a,b) buildin(iv,#a,b)
  357.  
  358.     iv->builtintbl = NewSymTable(iv->category, 191);
  359.  
  360.     BUILDIN(alloca,ALLOCA);
  361.     BUILDIN(strlen,STRLEN);
  362.     BUILDIN(strcpy,STRCPY);
  363.     BUILDIN(strcat,STRCAT);
  364.     BUILDIN(memcpy,MEMCPY);
  365.     BUILDIN(memmove,MEMMOVE);
  366.     BUILDIN(bzero,BZERO);
  367.     BUILDIN(malloc,MALLOC);
  368.     BUILDIN(calloc,CALLOC);
  369.     BUILDIN(realloc,REALLOC);         
  370.     BUILDIN(setjmp,SETJMP);
  371.     BUILDIN(longjmp,LONGJMP);
  372.     BUILDIN(abort,ABORT);
  373.     BUILDIN(exit, EXIT);
  374.     BUILDIN(_exit,EXIT);
  375.     BUILDIN(bterpdebug,DEBUG);
  376.     BUILDIN(bterpnodebug,NODEBUG);
  377.  
  378. #undef BUILDIN
  379. }
  380. static long
  381. final_strofs(Piv iv, char *string)
  382. {
  383. long *result;
  384.  
  385.     if(StringFind(iv->finalsymtbl, string, &result))
  386.         return result[2];    
  387.     return 0;
  388. }
  389. static short
  390. final_symnum(Piv iv, short symnum)
  391. {
  392. long *result;
  393.  
  394.     if(StringFind(iv->finalsymtbl, iv->symaddr[symnum], &result)) {
  395.         return result[1]-1;
  396.     }
  397.     return 0;
  398. }
  399. static void
  400. make_final_symtab(Piv iv)
  401. {
  402. int i;
  403.     iv->finalsymtbl = NewSymTable(iv->category, 0);
  404.     if(SymHead(iv->gbltbl))
  405.     {
  406.         i = 0;
  407.         while(SymNext(iv->gbltbl))
  408.         {
  409.         long *result;
  410.         struct _gloval *valp;
  411.  
  412.             SymValue(iv->gbltbl, &valp);
  413.             if(*(valp->p))
  414.             {
  415.             long key[2];
  416.                 key[0] = valp->pf->symtran[valp->symnum];
  417.                 key[1] = 0;
  418.                 if(!SymFind(iv->builtintbl, key, NULL))
  419.                 {
  420.                   if(!StringInsert(iv->finalsymtbl, valp->symname, &result))
  421.                   {/* New Entry */
  422.                     result[1] = ++i;
  423.                   }
  424.                 }
  425.             }
  426.         }
  427.     }
  428. }
  429. static void
  430. adjust_labels(Piv iv, long base, long adjust)
  431. {
  432. long *key;
  433. long *val;
  434.     if(SymHead(iv->newlabeltbl))
  435.     {
  436.         while(SymNext(iv->newlabeltbl))
  437.         {
  438.             SymKey(iv->newlabeltbl, &key);
  439.             SymValue(iv->newlabeltbl, &val);
  440.             if(key[1] == iv->filenum &&    val[0] > base) {
  441.                 val[0] += adjust;
  442.             }
  443.         }
  444.     }
  445. }
  446. static void
  447. addto_extlist(Piv iv, char *buf)
  448. {
  449. void *next;
  450.     while(iv->extmark > 0)
  451.     {
  452.     long offset = iv->markedbuf[iv->extmark] - buf;
  453.         next = iv->extbuf;
  454.         if(iv->extbufcnt >= sizeof(struct _el))
  455.         {
  456.             iv->extbuf++;
  457.         }
  458.         else
  459.         {
  460.             iv->extbufcnt = 4080;
  461.             iv->extbuf = Ccalloc(FUNCDATA, 1, iv->extbufcnt);
  462.         }
  463.         *((void**)next) = iv->extbuf;
  464.         iv->extbuf->spot = iv->out_offset+iv->func_offset+offset;
  465.         iv->extbuf->symnum = iv->markedsym[iv->extmark];
  466.         ++iv->extcnt;
  467.         --iv->extmark;
  468.         iv->extbufcnt -= sizeof(struct _el);
  469.     }
  470. }
  471. static void
  472. save_extlocs(Piv iv)
  473. {
  474. PEL pel = iv->extbufstart;
  475. void *next;
  476.  
  477.     while(pel)
  478.     {
  479.         next = iv->finextbuf;
  480.         if(iv->finextbufcnt >= sizeof(struct _el))
  481.         {
  482.             iv->finextbuf++;
  483.         }
  484.         else
  485.         {
  486.             iv->finextbufcnt = 4080;
  487.             iv->finextbuf = Ccalloc(iv->category, 1, iv->finextbufcnt);
  488.         }
  489.         *((void**)next) = iv->finextbuf;
  490.         iv->finextbuf->spot = pel->spot;
  491.         iv->finextbuf->symnum = pel->symnum;
  492.         ++iv->finextcnt;
  493.         iv->finextbufcnt -= sizeof(struct _el);
  494.         pel = pel->next;
  495.     }
  496. }
  497. static void
  498. adjust_externs(Piv iv, long base, long adjust)
  499. {
  500. PEL pel = iv->extbufstart;
  501.  
  502.     while(pel)
  503.     {
  504.         if(pel->spot > base)
  505.             pel->spot += adjust;
  506.         pel = pel->next;
  507.     }
  508. }
  509.  
  510. static int
  511. shorten_jmps(Piv iv)
  512. {
  513. int scnt;
  514. PJL jp;
  515. long jmp_offset;
  516. long label_offset;
  517. long diff;
  518. long offset_adjust;
  519. int sign;
  520. unsigned char *q, *osiz;
  521. int cursize, newsize;
  522.  
  523.     scnt = 0;
  524.     jp = iv->jbufstart;
  525.     offset_adjust = 0;
  526.     while(jp)
  527.     {
  528.         osiz = jp->q+4;                /* points to size in obuf */
  529.         q = osiz+4;                    /* points to the JMP inst in obuf */
  530.         cursize = *q & 3;            /* from the output bytecode */
  531.         jmp_offset = jp->offset + offset_adjust;
  532.         jp->offset = jmp_offset;    /* reset the offset for this inst */
  533.         label_offset = *jp->plabelval;
  534.         diff = label_offset - jmp_offset;
  535.  
  536.         sign = 1;
  537.         if(diff < 0)
  538.         {
  539.             sign = -1;
  540.             diff = -diff;
  541.         }
  542.         if(diff < 0x7fL)
  543.             newsize = 0;
  544.         else if(diff < 0x7fffL)
  545.             newsize = 1;
  546.         else if(diff < 0x007fffffL)
  547.             newsize = 2;
  548.         else
  549.             newsize = 3;
  550.         if(cursize != newsize)
  551.         {/* DO SOMETHING */
  552.         long adj;
  553.         static long codesize[4] = {2L,3L,4L,5L};
  554.             ++scnt;                                /* something changed */
  555.             *q &= 0xfc;                        /* mask opcode */
  556.             *q |= newsize;                    /* set size in opcode */
  557.             *((long*)osiz) = codesize[newsize];    /* set new output size */
  558.             adj = codesize[newsize] - codesize[cursize];
  559.             offset_adjust += adj;    /* jmps below this point have new offset */
  560.             if(sign > 0) diff += adj;    /* label is below this point */
  561.  
  562.             /* Adjust all labels below this point */
  563.             adjust_labels(iv, jmp_offset, adj);
  564.             /* adjust all external address spots (text relocs) below this point */
  565.             adjust_externs(iv, jmp_offset, adj);
  566.         }
  567.         diff *= sign;    /* restore sign to the relative address */
  568.  
  569.         /* generate the pc relative address */
  570.  
  571.         ++q;    /* points the the address field of the JMP inst */
  572.         if(newsize == 0)
  573.             *((signed char*)q) = (signed char)(diff & 0xff);
  574.         else if(newsize == 1)
  575.             *((short*)q) = (short)(diff & 0xffff);
  576.         else if(newsize == 2)
  577.             *((long*)q) = diff<<8;
  578.         else
  579.             *((long*)q) = diff;
  580.         jp = jp->next;
  581.     }/* END: while (jp) */
  582.  
  583.     return scnt;
  584. }
  585.  
  586. static void
  587. setup_jmps(Piv iv, unsigned char *pdef)
  588. {
  589. struct {
  590.     long k1;
  591.     long k2;
  592. } key;    
  593. long *result;
  594. PJL jp;
  595. unsigned char *p;
  596.  
  597.     jp = iv->jbufstart;
  598.     while(jp)
  599.     {
  600.         p = jp->p;
  601.         key.k1 = GL( POP->data );    /* label number from source code */
  602.         key.k2 = iv->filenum;            /* source file number */
  603.         if(SymFind(iv->newlabeltbl, &key, &result))
  604.         {
  605.             jp->plabelval = result;    /* save pointer to label value */
  606.         }
  607.         else
  608.         {
  609.         PERROR(pName ":SYSERROR: jmp setup failed for `%s' label=%d file=%d p=%x code=%d\n",
  610.         iv->symaddr[GL(((Pop)pdef)->data)], key.k1, key.k2, p, *p);
  611.         }
  612.         jp = jp->next;
  613.     }
  614. }
  615. static void
  616. addto_jmplist(Piv iv, unsigned char *p, void *q)
  617. {
  618. void *next = iv->jbuf;
  619.  
  620.     if(iv->jbufcnt >= sizeof(struct _jl))
  621.     {
  622.         iv->jbuf++;
  623.     }
  624.     else
  625.     {
  626.         iv->jbufcnt = 4080;
  627.         iv->jbuf = Ccalloc(FUNCDATA, 1, iv->jbufcnt);
  628.     }
  629.     *((void**)next) = iv->jbuf;
  630.     iv->jbuf->p = p;
  631.     iv->jbuf->q = q;
  632.     iv->jbuf->offset = iv->out_offset+iv->func_offset-5;
  633.     iv->jbufcnt -= sizeof(struct _jl);
  634. }
  635. static void
  636. save_maxdepth(Piv iv, long symnum)
  637. {
  638. long key[2];
  639. long val[3];
  640.  
  641.     if(iv->functbl == 0)
  642.     {
  643.         iv->functbl = NewSymTable(iv->category, 277);
  644.     }
  645.     key[0] = symnum;
  646.     key[1] = 0;
  647.     val[0] = iv->maxdepth + (4*iv->numnested);
  648.     val[1] = iv->mindepth;    
  649.     val[2] = 0;
  650.     SymInsert(iv->functbl, key, val, 12);
  651. }    
  652. static long
  653. get_maxdepth(Piv iv, short symnum)
  654. {
  655. long key[2];
  656. long *result;
  657.  
  658.     key[0] = symnum;
  659.     key[1] = 0;
  660.     if(SymFind(iv->functbl, key, &result))
  661.     {
  662.         return result[0];
  663.     }
  664.     return 0;
  665. }
  666. static void
  667. printline(Piv iv, void *ptr)
  668. {
  669.     fprintf(iv->outfile, "Line:%ld:\n", *((long*)ptr));
  670. }
  671. static int
  672. print8(Piv iv, unsigned char *ptr, int size, long offset, int lf)
  673. {
  674. char buf[40];
  675. int i, j=0;
  676.  
  677.     i = sprintf(buf, "%8.8lx: ", offset);
  678.     while(j < size && j < 8)
  679.     {
  680.         i += sprintf(&buf[i], "%2.2x ", *ptr++);
  681.         ++j;
  682.     }
  683.     if(lf)
  684.         buf[i++] = '\n';
  685.     else
  686.     {
  687.         while(i < 35)
  688.             buf[i++] = ' ';
  689.     }
  690.     buf[i] = 0;
  691.     fprintf(iv->outfile, buf);
  692.     return j;
  693. }
  694. static void
  695. printinst(Piv iv, unsigned char *pc, long size)
  696. {
  697. int i, bufcnt;
  698. unsigned char *epc;
  699. char *pbuf[20];
  700.  
  701.   bufcnt = 0;
  702.   epc = pc + size;
  703.   for( ;pc < epc; ++pc)
  704.   {
  705.     switch(*pc)
  706.     {
  707.         case LOCATE|J1:
  708.         case LOCATE|J2:
  709.         case LOCATE|J3:
  710.         case LOCATE|J4:
  711.             pbuf[bufcnt++] = "locate|";
  712.             pbuf[bufcnt++] = Jbuf[*pc & 0x03];
  713.             pc += Jcnt[*pc & 0x03];
  714.             break;
  715.         case LS|A1|B1:
  716.         case LS|A1|B2:
  717.         case LS|A1|B4:
  718.         case LS|A1|B8:
  719.         case LS|A2|B1:
  720.         case LS|A2|B2:
  721.         case LS|A2|B4:
  722.         case LS|A2|B8:
  723.         case LS|A3|B1:
  724.         case LS|A3|B2:
  725.         case LS|A3|B4:
  726.         case LS|A3|B8:
  727.             pbuf[bufcnt++] = "ls|";
  728.             pbuf[bufcnt++] = ABbuf[*pc & 0x0f];
  729.             pc += Acnt[(*pc>>2) & 0x03];
  730.             break;
  731.         case NEG|BYTE:
  732.         case NEG|SHORT:
  733.         case NEG|LONG:
  734.         case NEG|UBYTE:
  735.         case NEG|USHORT:
  736.         case NEG|ULONG:
  737.         case NEG|FLOAT:
  738.         case NEG|DOUBLE:
  739.             pbuf[bufcnt++] = "neg|";
  740.             pbuf[bufcnt++] = Tbuf[*pc & 0x07];
  741.             break;
  742.  
  743.         case LM|A1|B1:
  744.         case LM|A1|B2:
  745.         case LM|A1|B4:
  746.         case LM|A1|B8:
  747.         case LM|A2|B1:
  748.         case LM|A2|B2:
  749.         case LM|A2|B4:
  750.         case LM|A2|B8:
  751.         case LM|A3|B1:
  752.         case LM|A3|B2:
  753.         case LM|A3|B4:
  754.         case LM|A3|B8:
  755.         case LM|A4|B1:
  756.         case LM|A4|B2:
  757.         case LM|A4|B4:
  758.         case LM|A4|B8:
  759.             pbuf[bufcnt++] = "lm|";
  760.             pbuf[bufcnt++] = ABbuf[*pc & 0x0f];
  761.             pc += Acnt[(*pc>>2) & 0x03];
  762.             break;
  763.  
  764.         case COMP|B1:
  765.         case COMP|B2:
  766.         case COMP|B4:
  767.         case COMP|B8:
  768.             pbuf[bufcnt++] = "comp|";
  769.             pbuf[bufcnt++] = Bbuf[*pc & 0x03];
  770.             break;
  771.  
  772.         case JMP|J1:
  773.         case JMP|J2:
  774.         case JMP|J3:
  775.         case JMP|J4:
  776.             pbuf[bufcnt++] = "jmp|";
  777.             pbuf[bufcnt++] = Jbuf[*pc & 0x03];
  778.             pc += Jcnt[*pc & 0x03];
  779.             break;
  780.  
  781.         case JMPT|J1:
  782.         case JMPT|J2:
  783.         case JMPT|J3:
  784.         case JMPT|J4:
  785.             pbuf[bufcnt++] = "jmpt|";
  786.             pbuf[bufcnt++] = Jbuf[*pc & 0x03];
  787.             pc += Jcnt[*pc & 0x03];
  788.             break;
  789.  
  790.         case LJMPT|J1:
  791.         case LJMPT|J2:
  792.         case LJMPT|J3:
  793.         case LJMPT|J4:
  794.             pbuf[bufcnt++] = "ljmpt|";
  795.             pbuf[bufcnt++] = Jbuf[*pc & 0x03];
  796.             pc += Jcnt[*pc & 0x03];
  797.             break;
  798.  
  799.         case JMPF|J1:
  800.         case JMPF|J2:
  801.         case JMPF|J3:
  802.         case JMPF|J4:
  803.             pbuf[bufcnt++] = "jmpf|";
  804.             pbuf[bufcnt++] = Jbuf[*pc & 0x03];
  805.             pc += Jcnt[*pc & 0x03];
  806.             break;
  807.  
  808.         case LJMPF|J1:
  809.         case LJMPF|J2:
  810.         case LJMPF|J3:
  811.         case LJMPF|J4:
  812.             pbuf[bufcnt++] = "ljmpf|";
  813.             pbuf[bufcnt++] = Jbuf[*pc & 0x03];
  814.             pc += Jcnt[*pc & 0x03];
  815.             break;
  816.  
  817.         case NOT|B1:
  818.         case NOT|B2:
  819.         case NOT|B4:    /* also FLOAT */
  820.         case NOT|B8:    /* also DOUBLE */
  821.             pbuf[bufcnt++] = "not|";
  822.             pbuf[bufcnt++] = Bbuf[*pc & 0x03];
  823.             break;
  824.  
  825.         case SS|A1|B1:
  826.         case SS|A1|B2:
  827.         case SS|A1|B4:
  828.         case SS|A1|B8:
  829.         case SS|A2|B1:
  830.         case SS|A2|B2:
  831.         case SS|A2|B4:
  832.         case SS|A2|B8:
  833.         case SS|A3|B1:
  834.         case SS|A3|B2:
  835.         case SS|A3|B4:
  836.         case SS|A3|B8:
  837.             pbuf[bufcnt++] = "ss|";
  838.             pbuf[bufcnt++] = ABbuf[*pc & 0x0f];
  839.             pc += Acnt[(*pc>>2) & 0x03];
  840.             break;
  841.  
  842.         case TRUTHOF|B2:
  843.         case TRUTHOF|B4:
  844.         case TRUTHOF|B8:
  845.             pbuf[bufcnt++] = "truthof|";
  846.             pbuf[bufcnt++] = Bbuf[*pc & 0x03];
  847.             break;
  848.         case CVT:
  849.         {
  850.         unsigned char cvs,cvd;
  851.             pbuf[bufcnt++] = "cvt ";
  852.             ++pc;
  853.             cvs = (*pc & 0x70)>>4;
  854.             cvd = (*pc & 0x07);
  855.             pbuf[bufcnt++] = Tbuf[cvd];
  856.             pbuf[bufcnt++] = "<-";
  857.             pbuf[bufcnt++] = Tbuf[cvs];
  858.             break;
  859.         }
  860.         case LI|B1:
  861.         case LI|B2:
  862.         case LI|B4:
  863.         case LI|B8:
  864.             pbuf[bufcnt++] = "li|";
  865.             pbuf[bufcnt++] = Bbuf[*pc & 0x03];
  866.             pc += Bcnt[*pc & 0x03];
  867.             break;
  868.  
  869.         case LAI|D1:
  870.         case LAI|D2:
  871.         case LAI|D3:
  872.         case LAI|D4:
  873.             pbuf[bufcnt++] = "lai|";
  874.             pbuf[bufcnt++] = Dbuf[*pc & 0x03];
  875.             pc += Dcnt[*pc & 0x03];
  876.             break;
  877.  
  878.         case LUI|B1:
  879.         case LUI|B2:
  880.         case LUI|B4:
  881.         case LUI|B8:
  882.             pbuf[bufcnt++] = "lui|";
  883.             pbuf[bufcnt++] = Bbuf[*pc & 0x03];
  884.             pc += Bcnt[*pc & 0x03];
  885.             break;
  886.  
  887.         case IMMED:
  888.         {
  889.             ++pc;
  890.             switch(*pc)
  891.             {
  892.                 case SMI|A1|B1:
  893.                 case SMI|A1|B2:
  894.                 case SMI|A1|B4:
  895.                 case SMI|A1|B8:
  896.                 case SMI|A2|B1:
  897.                 case SMI|A2|B2:
  898.                 case SMI|A2|B4:
  899.                 case SMI|A2|B8:
  900.                 case SMI|A3|B1:
  901.                 case SMI|A3|B2:
  902.                 case SMI|A3|B4:
  903.                 case SMI|A3|B8:
  904.                 case SMI|A4|B1:
  905.                 case SMI|A4|B2:
  906.                 case SMI|A4|B4:
  907.                 case SMI|A4|B8:
  908.                     pbuf[bufcnt++] = "smi|";
  909.                     pbuf[bufcnt++] = ABbuf[*pc & 0x0f];
  910.                     pc += ABcnt[*pc & 0x0f];
  911.                     break;
  912.  
  913.                 case SSI|A1|B1:
  914.                 case SSI|A1|B2:
  915.                 case SSI|A1|B4:
  916.                 case SSI|A1|B8:
  917.                 case SSI|A2|B1:
  918.                 case SSI|A2|B2:
  919.                 case SSI|A2|B4:
  920.                 case SSI|A2|B8:
  921.                 case SSI|A3|B1:
  922.                 case SSI|A3|B2:
  923.                 case SSI|A3|B4:
  924.                 case SSI|A3|B8:
  925.                     pbuf[bufcnt++] = "ssi|";
  926.                     pbuf[bufcnt++] = ABbuf[*pc & 0x0f];
  927.                     pc += ABcnt[*pc & 0x0f];
  928.                     break;
  929.  
  930.                 case MODI|BYTE:
  931.                 case MODI|SHORT:
  932.                 case MODI|LONG:
  933.                 case MODI|UBYTE:
  934.                 case MODI|USHORT:
  935.                 case MODI|ULONG:
  936.                     pbuf[bufcnt++] = "modi|";
  937.                     pbuf[bufcnt++] = Tbuf[*pc & 0x07];
  938.                     pc += 2;
  939.                     break;
  940.  
  941.                 case DEREF|BYTE:
  942.                 case DEREF|SHORT:
  943.                 case DEREF|LONG:
  944.                 case DEREF|UBYTE:
  945.                 case DEREF|USHORT:
  946.                 case DEREF|ULONG:
  947.                 case DEREF|FLOAT:
  948.                 case DEREF|DOUBLE:
  949.                     pbuf[bufcnt++] = "deref|";
  950.                     pbuf[bufcnt++] = Tbuf[*pc & 0x07];
  951.                     break;
  952.  
  953.                 case DEREF1|BYTE:
  954.                 case DEREF1|SHORT:
  955.                 case DEREF1|LONG:
  956.                 case DEREF1|UBYTE:
  957.                 case DEREF1|USHORT:
  958.                 case DEREF1|ULONG:
  959.                 case DEREF1|FLOAT:
  960.                 case DEREF1|DOUBLE:
  961.                     pbuf[bufcnt++] = "deref1|";
  962.                     pbuf[bufcnt++] = Tbuf[*pc & 0x07];
  963.                     break;
  964.             }
  965.             break;
  966.         }
  967.         case SM|A1|B1:
  968.         case SM|A1|B2:
  969.         case SM|A1|B4:
  970.         case SM|A1|B8:
  971.         case SM|A2|B1:
  972.         case SM|A2|B2:
  973.         case SM|A2|B4:
  974.         case SM|A2|B8:
  975.         case SM|A3|B1:
  976.         case SM|A3|B2:
  977.         case SM|A3|B4:
  978.         case SM|A3|B8:
  979.         case SM|A4|B1:
  980.         case SM|A4|B2:
  981.         case SM|A4|B4:
  982.         case SM|A4|B8:
  983.             pbuf[bufcnt++] = "sm|";
  984.             pbuf[bufcnt++] = ABbuf[*pc & 0x0f];
  985.             pc += Acnt[(*pc>>2) & 3];
  986.             break;
  987.  
  988.         case ADD|BYTE:
  989.         case ADD|SHORT:
  990.         case ADD|LONG:
  991.         case ADD|UBYTE:
  992.         case ADD|USHORT:
  993.         case ADD|ULONG:
  994.         case ADD|FLOAT:
  995.         case ADD|DOUBLE:
  996.             pbuf[bufcnt++] = "add|";
  997.             pbuf[bufcnt++] = Tbuf[*pc & 0x07];
  998.             break;
  999.  
  1000.         case SUB|BYTE:
  1001.         case SUB|SHORT:
  1002.         case SUB|LONG:
  1003.         case SUB|UBYTE:
  1004.         case SUB|USHORT:
  1005.         case SUB|ULONG:
  1006.         case SUB|FLOAT:
  1007.         case SUB|DOUBLE:
  1008.             pbuf[bufcnt++] = "sub|";
  1009.             pbuf[bufcnt++] = Tbuf[*pc & 0x07];
  1010.             break;
  1011.  
  1012.         case MUL|BYTE:
  1013.         case MUL|SHORT:
  1014.         case MUL|LONG:
  1015.         case MUL|UBYTE:
  1016.         case MUL|USHORT:
  1017.         case MUL|ULONG:
  1018.         case MUL|FLOAT:
  1019.         case MUL|DOUBLE:
  1020.             pbuf[bufcnt++] = "mul|";
  1021.             pbuf[bufcnt++] = Tbuf[*pc & 0x07];
  1022.             break;
  1023.  
  1024.         case DIV|BYTE:
  1025.         case DIV|SHORT:
  1026.         case DIV|LONG:
  1027.         case DIV|UBYTE:
  1028.         case DIV|USHORT:
  1029.         case DIV|ULONG:
  1030.         case DIV|FLOAT:
  1031.         case DIV|DOUBLE:
  1032.             pbuf[bufcnt++] = "div|";
  1033.             pbuf[bufcnt++] = Tbuf[*pc & 0x07];
  1034.             break;
  1035.  
  1036.         case OR|B1:
  1037.         case OR|B2:
  1038.         case OR|B4:
  1039.         case OR|B8:
  1040.             pbuf[bufcnt++] = "or|";
  1041.             pbuf[bufcnt++] = Bbuf[*pc & 0x03];
  1042.             break;
  1043.  
  1044.         case AND|B1:
  1045.         case AND|B2:
  1046.         case AND|B4:
  1047.         case AND|B8:
  1048.             pbuf[bufcnt++] = "and|";
  1049.             pbuf[bufcnt++] = Bbuf[*pc & 0x03];
  1050.             break;
  1051.  
  1052.         case MOD|BYTE:
  1053.         case MOD|SHORT:
  1054.         case MOD|LONG:
  1055.         case MOD|UBYTE:
  1056.         case MOD|USHORT:
  1057.         case MOD|ULONG:
  1058.             pbuf[bufcnt++] = "mod|";
  1059.             pbuf[bufcnt++] = Tbuf[*pc & 0x07];
  1060.             break;
  1061.  
  1062.         case XTD:
  1063.         {
  1064.             ++pc;
  1065.             switch(*pc)
  1066.             {
  1067.                 case LI:
  1068.                     pbuf[bufcnt++] = "li";
  1069.                     pc += XSZ;
  1070.                     break;
  1071.  
  1072.                 case LSH|B1:
  1073.                 case LSH|B2:
  1074.                 case LSH|B4:
  1075.                 case LSH|B8:
  1076.                     pbuf[bufcnt++] = "lsh|";
  1077.                     pbuf[bufcnt++] = Bbuf[*pc & 0x03];
  1078.                     break;
  1079.  
  1080.                 case LSHI|B1:
  1081.                 case LSHI|B2:
  1082.                 case LSHI|B4:
  1083.                 case LSHI|B8:
  1084.                     pbuf[bufcnt++] = "lshi|";
  1085.                     pbuf[bufcnt++] = Bbuf[*pc & 0x03];
  1086.                     ++pc;
  1087.                     break;
  1088.  
  1089.                 case RSH|BYTE:
  1090.                 case RSH|SHORT:
  1091.                 case RSH|LONG:
  1092.                 case RSH|UBYTE:
  1093.                 case RSH|USHORT:
  1094.                 case RSH|ULONG:
  1095.                     pbuf[bufcnt++] = "rsh|";
  1096.                     pbuf[bufcnt++] = Tbuf[*pc & 0x07];
  1097.                     break;
  1098.  
  1099.                 case RSHI|BYTE:
  1100.                 case RSHI|SHORT:
  1101.                 case RSHI|LONG:
  1102.                 case RSHI|UBYTE:
  1103.                 case RSHI|USHORT:
  1104.                 case RSHI|ULONG:
  1105.                     pbuf[bufcnt++] = "rshi|";
  1106.                     pbuf[bufcnt++] = Tbuf[*pc & 0x07];
  1107.                     ++pc;
  1108.                     break;
  1109.  
  1110.                 case BUILTIN:
  1111.                 {
  1112.                     pbuf[bufcnt++] = "builtin ";
  1113.                     ++pc;
  1114.                     pbuf[bufcnt++] = BUbuf[*pc];
  1115.                     break;
  1116.                 } /* END: XTD BUILTIN */
  1117.                 case CLRDAT:
  1118.                     pbuf[bufcnt++] = "clrdat";
  1119.                     break;
  1120.                 case SWITCH:
  1121.                     pbuf[bufcnt++] = "switch";
  1122.                     pc += 2;
  1123.                     break;
  1124.                 case CALLSETUP:
  1125.                     pbuf[bufcnt++] = "callsetup";
  1126.                     pc += 4;
  1127.                     break;
  1128.                 case RETSTRUCT:
  1129.                     pbuf[bufcnt++] = "retstruct";
  1130.                     pc += 4;
  1131.                     break;
  1132.                 case PRUNESTRUCT:
  1133.                     pbuf[bufcnt++] = "prunestruct";
  1134.                     break;
  1135.                 case GETBITFIELD:
  1136.                     pbuf[bufcnt++] = "getbitfield";
  1137.                     pc += 3;
  1138.                     break;
  1139.                 case PUTBITFIELD:
  1140.                     pbuf[bufcnt++] = "putbitfield";
  1141.                     pc += 3;
  1142.                     break;
  1143.                 case IMMED:
  1144.                 {
  1145.                     ++pc;
  1146.                     switch(*pc)
  1147.                     {
  1148.                         case SMI|A1:
  1149.                         case SMI|A2:
  1150.                         case SMI|A3:
  1151.                         case SMI|A4:
  1152.                             pbuf[bufcnt++] = "smi|";
  1153.                             pbuf[bufcnt++] = Abuf[(*pc>>2) & 0x03];
  1154.                             pc += Acnt[(*pc>>2) & 0x03] + XSZ;
  1155.                             break;
  1156.  
  1157.                         case SSI|A1:
  1158.                         case SSI|A2:
  1159.                         case SSI|A3:
  1160.                             pbuf[bufcnt++] = "ssi|";
  1161.                             pbuf[bufcnt++] = Abuf[(*pc>>2) & 0x03];
  1162.                             pc += Acnt[(*pc>>2) & 0x03] + XSZ;
  1163.                             break;
  1164.  
  1165.                         case MODI|LONGLONG:
  1166.                         case MODI|ULONGLONG:
  1167.                             pbuf[bufcnt++] = "modi|";
  1168.                             pbuf[bufcnt++] = XTbuf[*pc & 0x03];
  1169.                             pc += 2;
  1170.                             break;
  1171.  
  1172.                         case DEREF|LONGLONG:
  1173.                         case DEREF|ULONGLONG:
  1174.                         case DEREF|LONGDOUBLE:
  1175.                             pbuf[bufcnt++] = "deref|";
  1176.                             pbuf[bufcnt++] = XTbuf[*pc & 0x03];
  1177.                             break;
  1178.  
  1179.                         case DEREF1|LONGLONG:
  1180.                         case DEREF1|ULONGLONG:
  1181.                         case DEREF1|LONGDOUBLE:
  1182.                             pbuf[bufcnt++] = "deref1|";
  1183.                             pbuf[bufcnt++] = XTbuf[*pc & 0x03];
  1184.                             break;
  1185.                     }
  1186.                     break;
  1187.                 }/* END: XTD IMMED */
  1188.                 
  1189.                 case ADD|LONGLONG:
  1190.                 case ADD|ULONGLONG:
  1191.                 case ADD|LONGDOUBLE:
  1192.                     pbuf[bufcnt++] = "add|";
  1193.                     pbuf[bufcnt++] = XTbuf[*pc & 0x03];
  1194.                     break;
  1195.                 case SUB|LONGLONG:
  1196.                 case SUB|ULONGLONG:
  1197.                 case SUB|LONGDOUBLE:
  1198.                     pbuf[bufcnt++] = "sub|";
  1199.                     pbuf[bufcnt++] = XTbuf[*pc & 0x03];
  1200.                 case MUL|LONGLONG:
  1201.                 case MUL|ULONGLONG:
  1202.                 case MUL|LONGDOUBLE:
  1203.                     pbuf[bufcnt++] = "mul|";
  1204.                     pbuf[bufcnt++] = XTbuf[*pc & 0x03];
  1205.                     break;
  1206.                 case DIV|LONGLONG:
  1207.                 case DIV|ULONGLONG:
  1208.                 case DIV|LONGDOUBLE:
  1209.                     pbuf[bufcnt++] = "div|";
  1210.                     pbuf[bufcnt++] = XTbuf[*pc & 0x03];
  1211.                     break;
  1212.                 case LT|LONGLONG:
  1213.                 case LT|ULONGLONG:
  1214.                 case LT|LONGDOUBLE:
  1215.                     pbuf[bufcnt++] = "lt|";
  1216.                     pbuf[bufcnt++] = XTbuf[*pc & 0x03];
  1217.                     break;
  1218.                 case GT|LONGLONG:
  1219.                  case GT|ULONGLONG:
  1220.                 case GT|LONGDOUBLE:
  1221.                     pbuf[bufcnt++] = "gt|";
  1222.                     pbuf[bufcnt++] = XTbuf[*pc & 0x03];
  1223.                     break;
  1224.                 case LE|LONGLONG:
  1225.                 case LE|ULONGLONG:
  1226.                 case LE|LONGDOUBLE:
  1227.                     pbuf[bufcnt++] = "le|";
  1228.                     pbuf[bufcnt++] = XTbuf[*pc & 0x03];
  1229.                     break;
  1230.                 case GE|LONGLONG:
  1231.                 case GE|ULONGLONG:
  1232.                 case GE|LONGDOUBLE:
  1233.                     pbuf[bufcnt++] = "ge|";
  1234.                     pbuf[bufcnt++] = XTbuf[*pc & 0x03];
  1235.                     break;
  1236.                 case NE|LONGLONG:
  1237.                 case NE|ULONGLONG:
  1238.                 case NE|LONGDOUBLE:
  1239.                     pbuf[bufcnt++] = "ne|";
  1240.                     pbuf[bufcnt++] = XTbuf[*pc & 0x03];
  1241.                     break;
  1242.                 case EQ|LONGLONG:
  1243.                 case EQ|ULONGLONG:
  1244.                 case EQ|LONGDOUBLE:
  1245.                     pbuf[bufcnt++] = "eq|";
  1246.                     pbuf[bufcnt++] = XTbuf[*pc & 0x03];
  1247.                     break;
  1248.                 case NEG|LONGLONG:
  1249.                 case NEG|ULONGLONG:
  1250.                 case NEG|LONGDOUBLE:
  1251.                     pbuf[bufcnt++] = "neg|";
  1252.                     pbuf[bufcnt++] = XTbuf[*pc & 0x03];
  1253.                     break;
  1254.                 case NOT|BX:
  1255.                     pbuf[bufcnt++] = "not|BX";
  1256.                     break;
  1257.                 case COMP|LONGLONG:
  1258.                 case COMP|ULONGLONG:
  1259.                     pbuf[bufcnt++] = "comp|";
  1260.                     pbuf[bufcnt++] = XTbuf[*pc & 0x03];
  1261.                     break;
  1262.                 case RSH|SLONGLONG:
  1263.                 case RSH|SULONGLONG:
  1264.                     pbuf[bufcnt++] = "rsh|";
  1265.                     pbuf[bufcnt++] = XTbuf[*pc & 0x03];
  1266.                     break;
  1267.  
  1268.                 case MOD|LONGLONG:
  1269.                 case MOD|ULONGLONG:
  1270.                     pbuf[bufcnt++] = "mod|";
  1271.                     pbuf[bufcnt++] = XTbuf[*pc & 0x03];
  1272.                     break;
  1273.                 case RSHI|SLONGLONG:
  1274.                 case RSHI|SULONGLONG:
  1275.                     pbuf[bufcnt++] = "rshi|";
  1276.                     pbuf[bufcnt++] = XTbuf[*pc & 0x07];
  1277.                     ++pc;
  1278.                     break;
  1279.                 case TRUTHOF|BX:
  1280.                     pbuf[bufcnt++] = "truthof|BX";
  1281.                     break;
  1282.  
  1283.                 case LS|A1:
  1284.                 case LS|A2:
  1285.                 case LS|A3:
  1286.                     pbuf[bufcnt++] = "xtd ls|";
  1287.                     pbuf[bufcnt++] = Abuf[(*pc>>2) & 0x03];
  1288.                     pc += Acnt[(*pc>>2) & 0x03];
  1289.                     break;
  1290.  
  1291.                 case LM|A1:
  1292.                 case LM|A2:
  1293.                 case LM|A3:
  1294.                 case LM|A4:
  1295.                     pbuf[bufcnt++] = "xtd lm|";
  1296.                     pbuf[bufcnt++] = Abuf[(*pc>>2) & 0x03];
  1297.                     pc += Acnt[(*pc>>2) & 0x03];
  1298.                     break;
  1299.  
  1300.                 case SS|A1:
  1301.                 case SS|A2:
  1302.                 case SS|A3:
  1303.                     pbuf[bufcnt++] = "xtd ss|";
  1304.                     pbuf[bufcnt++] = Abuf[(*pc>>2) & 0x03];
  1305.                     pc += Acnt[(*pc>>2) & 0x03];
  1306.                     break;
  1307.  
  1308.                 case SM|A1:
  1309.                 case SM|A2:
  1310.                 case SM|A3:
  1311.                 case SM|A4:
  1312.                     pbuf[bufcnt++] = "xtd sm|";
  1313.                     pbuf[bufcnt++] = Abuf[(*pc>>2) & 0x03];
  1314.                     pc += Acnt[(*pc>>2) & 0x03];
  1315.                     break;
  1316.  
  1317.                 case MOVSS:
  1318.                     pbuf[bufcnt++] = "xtd movss";
  1319.                     ++pc;
  1320.                     pbuf[bufcnt++] = SDbuf[*pc & 0x0f];
  1321.                     pc += SDcnt[*pc & 0x0f];
  1322.                     break;
  1323.                 case MOVSM:
  1324.                     pbuf[bufcnt++] = "xtd movsm";
  1325.                     ++pc;
  1326.                     pbuf[bufcnt++] = SDbuf[*pc & 0x0f];
  1327.                     pc += SDcnt[*pc & 0x0f];
  1328.                     break;
  1329.                 case MOVMS:
  1330.                     pbuf[bufcnt++] = "xtd movms";
  1331.                     ++pc;
  1332.                     pbuf[bufcnt++] = SDbuf[*pc & 0x0f];
  1333.                     pc += SDcnt[*pc & 0x0f];
  1334.                     break;
  1335.                 case MOVMM:
  1336.                     pbuf[bufcnt++] = "xtd movmm";
  1337.                     ++pc;
  1338.                     pbuf[bufcnt++] = SDbuf[*pc & 0x0f];
  1339.                     pc += SDcnt[*pc & 0x0f];
  1340.                     break;
  1341.             }
  1342.             break;
  1343.         }/* END: XTD */
  1344.  
  1345.         case XOR|B1:
  1346.         case XOR|B2:
  1347.         case XOR|B4:
  1348.         case XOR|B8:
  1349.             pbuf[bufcnt++] = "xor|";
  1350.             pbuf[bufcnt++] = Bbuf[*pc & 0x03];
  1351.             break;
  1352.  
  1353.         case GT|BYTE:
  1354.         case GT|SHORT:
  1355.         case GT|LONG:
  1356.         case GT|UBYTE:
  1357.         case GT|USHORT:
  1358.         case GT|ULONG:
  1359.         case GT|FLOAT:
  1360.         case GT|DOUBLE:
  1361.             pbuf[bufcnt++] = "gt|";
  1362.             pbuf[bufcnt++] = Tbuf[*pc & 0x07];
  1363.             break;
  1364.  
  1365.         case LT|BYTE:
  1366.         case LT|SHORT:
  1367.         case LT|LONG:
  1368.         case LT|UBYTE:
  1369.         case LT|USHORT:
  1370.         case LT|ULONG:
  1371.         case LT|FLOAT:
  1372.         case LT|DOUBLE:
  1373.             pbuf[bufcnt++] = "lt|";
  1374.             pbuf[bufcnt++] = Tbuf[*pc & 0x07];
  1375.             break;
  1376.  
  1377.         case GE|BYTE:
  1378.         case GE|SHORT:
  1379.         case GE|LONG:
  1380.         case GE|UBYTE:
  1381.         case GE|USHORT:
  1382.         case GE|ULONG:
  1383.         case GE|FLOAT:
  1384.         case GE|DOUBLE:
  1385.             pbuf[bufcnt++] = "ge|";
  1386.             pbuf[bufcnt++] = Tbuf[*pc & 0x07];
  1387.             break;
  1388.  
  1389.         case LE|BYTE:
  1390.         case LE|SHORT:
  1391.         case LE|LONG:
  1392.         case LE|UBYTE:
  1393.         case LE|USHORT:
  1394.         case LE|ULONG:
  1395.         case LE|FLOAT:
  1396.         case LE|DOUBLE:
  1397.             pbuf[bufcnt++] = "le|";
  1398.             pbuf[bufcnt++] = Tbuf[*pc & 0x07];
  1399.             break;
  1400.  
  1401.         case NE|BYTE:
  1402.         case NE|SHORT:
  1403.         case NE|LONG:
  1404.         case NE|UBYTE:
  1405.         case NE|USHORT:
  1406.         case NE|ULONG:
  1407.         case NE|FLOAT:
  1408.         case NE|DOUBLE:
  1409.             pbuf[bufcnt++] = "ne|";
  1410.             pbuf[bufcnt++] = Tbuf[*pc & 0x07];
  1411.             break;
  1412.  
  1413.         case EQ|BYTE:
  1414.         case EQ|SHORT:
  1415.         case EQ|LONG:
  1416.         case EQ|UBYTE:
  1417.         case EQ|USHORT:
  1418.         case EQ|ULONG:
  1419.         case EQ|FLOAT:
  1420.         case EQ|DOUBLE:
  1421.             pbuf[bufcnt++] = "eq|";
  1422.             pbuf[bufcnt++] = Tbuf[*pc & 0x07];
  1423.             break;
  1424.  
  1425.         case ARG:
  1426.             pbuf[bufcnt++] = "arg";
  1427.             break;
  1428.         case ARGA:
  1429.             pbuf[bufcnt++] = "arga";
  1430.             break;
  1431.         case ARGF:
  1432.             pbuf[bufcnt++] = "argf";
  1433.             break;
  1434.  
  1435.         case MOVSS|B1:
  1436.         case MOVSS|B2:
  1437.         case MOVSS|B4:
  1438.         case MOVSS|B8:
  1439.             pbuf[bufcnt++] = "movss|";
  1440.             pbuf[bufcnt++] = Bbuf[*pc & 0x03];
  1441.             ++pc;
  1442.             pbuf[bufcnt++] = SDbuf[*pc & 0x0f];
  1443.             pc += SDcnt[*pc & 0x0f];
  1444.             break;
  1445.  
  1446.         case MOVSM|B1:
  1447.         case MOVSM|B2:
  1448.         case MOVSM|B4:
  1449.         case MOVSM|B8:
  1450.             pbuf[bufcnt++] = "movsm|";
  1451.             pbuf[bufcnt++] = Bbuf[*pc & 0x03];
  1452.             ++pc;
  1453.             pbuf[bufcnt++] = SDbuf[*pc & 0x0f];
  1454.             pc += SDcnt[*pc & 0x0f];
  1455.             break;
  1456.  
  1457.         case MOVMS|B1:
  1458.         case MOVMS|B2:
  1459.         case MOVMS|B4:
  1460.         case MOVMS|B8:
  1461.             pbuf[bufcnt++] = "movms|";
  1462.             pbuf[bufcnt++] = Bbuf[*pc & 0x03];
  1463.             ++pc;
  1464.             pbuf[bufcnt++] = SDbuf[*pc & 0x0f];
  1465.             pc += SDcnt[*pc & 0x0f];
  1466.             break;
  1467.  
  1468.         case MOVMM|B1:
  1469.         case MOVMM|B2:
  1470.         case MOVMM|B4:
  1471.         case MOVMM|B8:
  1472.             pbuf[bufcnt++] = "movmm|";
  1473.             pbuf[bufcnt++] = Bbuf[*pc & 0x03];
  1474.             ++pc;
  1475.             pbuf[bufcnt++] = SDbuf[*pc & 0x0f];
  1476.             pc += SDcnt[*pc & 0x0f];
  1477.             break;
  1478.  
  1479.         case DUMP:
  1480.             pbuf[bufcnt++] = "dump ";
  1481.             break;
  1482.         case REGAIN:
  1483.             pbuf[bufcnt++] = "regain ";
  1484.             break;
  1485.         case CALL:
  1486.             pbuf[bufcnt++] = "call ";
  1487.             break;
  1488.         case RET:
  1489.             pbuf[bufcnt++] = "ret ";
  1490.             break;
  1491.         case SWAP:
  1492.             pbuf[bufcnt++] = "swap ";
  1493.             break;
  1494.         case SWAP4:
  1495.             pbuf[bufcnt++] = "swap4 ";
  1496.             break;
  1497.         case SWAP4DEEP:
  1498.             pbuf[bufcnt++] = "swap4deep ";
  1499.             break;
  1500.         case DUP:
  1501.             pbuf[bufcnt++] = "dup ";
  1502.             break;
  1503.         case DUP4:
  1504.             pbuf[bufcnt++] = "dup4 ";
  1505.             break;
  1506.         case ABSMEM:
  1507.             pbuf[bufcnt++] = "absmem ";
  1508.             break;
  1509.         case ABSSTK:
  1510.             pbuf[bufcnt++] = "absstk ";
  1511.             break;
  1512.         case MOVDA1:
  1513.             pbuf[bufcnt++] = "movda1 ";
  1514.             break;
  1515.         case MOVDA2:
  1516.             pbuf[bufcnt++] = "movda2 ";
  1517.             break;
  1518.         case MOVDA4:
  1519.             pbuf[bufcnt++] = "movda4 ";
  1520.             break;
  1521.         case MOVDA8:
  1522.             pbuf[bufcnt++] = "movda8 ";
  1523.             break;
  1524.         case MOVDAX:
  1525.             pbuf[bufcnt++] = "movdax ";
  1526.             break;
  1527.         case MOVAA1:
  1528.             pbuf[bufcnt++] = "movaa1 ";
  1529.             break;
  1530.         case MOVAA2:
  1531.             pbuf[bufcnt++] = "movaa2 ";
  1532.             break;
  1533.         case MOVAA4:
  1534.             pbuf[bufcnt++] = "movaa4 ";
  1535.             break;
  1536.         case MOVAA8:
  1537.             pbuf[bufcnt++] = "movaa8 ";
  1538.             break;
  1539.         case MOVAAX:
  1540.             pbuf[bufcnt++] = "movaax ";
  1541.             break;
  1542.         case MOVAAC:
  1543.             pbuf[bufcnt++] = "movaac ";
  1544.             break;
  1545.         case NOP:
  1546.             pbuf[bufcnt++] = "nop ";
  1547.             break;
  1548.     } /* END: switch(*pc) */
  1549.   }/* END: for() */
  1550.   for(i = 0; i < bufcnt; ++i)
  1551.         fwrite(pbuf[i], 1, strlen(pbuf[i]), iv->outfile);
  1552.   fwrite("\n", 1, 1, iv->outfile);
  1553. }/* END: printinst() */
  1554. static void
  1555. disassemble(Piv iv, void *ptr, long size)
  1556. {
  1557. int x;
  1558. long offset = iv->out_offset;
  1559.  
  1560.     x = print8(iv, ptr, size, offset, 0);
  1561.     printinst(iv, ptr, size);
  1562.     while((size -= x) > 0)
  1563.     {
  1564.         offset += x;
  1565.         ((char*)ptr) += x;
  1566.         x = print8(iv, ptr, size, offset, 1);
  1567.     }
  1568. }
  1569. static void
  1570. reset_funcdata(Piv iv)
  1571. {
  1572.     iv->obuf = (char*)&iv->obufstart;
  1573.     iv->obufstart = 0;
  1574.     iv->obufcnt = 0;
  1575.     iv->func_offset = 0;
  1576.     iv->jbuf = (PJL)&iv->jbufstart;
  1577.     iv->jmpcnt = 0;
  1578.     iv->jbufcnt = 0;
  1579.     iv->jbufstart = 0;
  1580.     iv->extbuf = (PEL)&iv->extbufstart;
  1581.     iv->extcnt = 0;
  1582.     iv->extbufcnt = 0;
  1583.     iv->extbufstart = 0;
  1584.     iv->stackdepth = 0;
  1585.     iv->maxdepth = 0;
  1586.     iv->mindepth = 0;
  1587.     iv->numnested = 0;
  1588.     iv->cod_bufcnt = 0;
  1589.     iv->ob_bufcnt = 0;
  1590.     iv->cod_usedhead = 0;
  1591.     iv->ob_usedhead = 0;
  1592.     iv->first_cod = 0;
  1593.     iv->first_ob = 0;
  1594.     Cfreecat(FUNCDATA);
  1595. }
  1596. static void
  1597. write_funcdata(Piv iv, unsigned char *pdef)
  1598. {
  1599. long *p;
  1600.     if((p = (long*)iv->obufstart))
  1601.     {
  1602.         setup_jmps(iv, pdef);
  1603.         while(shorten_jmps(iv))
  1604.             ;
  1605.         while(p)
  1606.         {
  1607.             if(iv->listing_wanted)
  1608.             {
  1609.                 if(((unsigned char*)p)[8] == LINENO)
  1610.                 {
  1611.                     printline(iv, &((unsigned char*)p)[9]);
  1612.                 }
  1613.                 else if(((unsigned char*)p)[8] == NFUNC)
  1614.                 {
  1615.                 char *funcname = *((char**)&(((char*)p)[9]));
  1616.                     fprintf(iv->outfile, "\n%8.8lx:    .nested .function _%s\n",
  1617.                     iv->out_offset, funcname);
  1618.                 }
  1619.                 else
  1620.                 {
  1621.                     disassemble(iv, &p[2], p[1]);
  1622.                     iv->out_offset += p[1];
  1623.                 }
  1624.             }
  1625.             else
  1626.             {
  1627.                 FILEWRITE(&p[2],p[1]);
  1628.                 iv->out_offset += p[1];
  1629.             }
  1630.             p = (void*)p[0];
  1631.         }
  1632.     }
  1633. if(iv->debug >= '1')
  1634. cfeprintf("MAXDEPTH=%d MINDEPTH=%d func=%s\n",
  1635. iv->maxdepth, iv->mindepth, iv->symaddr[GL( ((Pop)pdef)->data )]);
  1636.  
  1637.     save_maxdepth(iv, GL( ((Pop)pdef)->data ));
  1638. }
  1639. static void *
  1640. write_obuf(Piv iv, unsigned char *buf, long cnt)
  1641. {/* Output first goes to a linked list */
  1642. void *next = iv->obuf;
  1643.  
  1644.     if(iv->obuf != (unsigned char*)&iv->obufstart)
  1645.     {/* Suppress duplicate RETs */
  1646.       if(buf[0] == RET && (iv->obuf[8] == RET || iv->obuf[9] == RETSTRUCT) )
  1647.       {
  1648.         return iv->obuf;
  1649.       }
  1650.     }
  1651.     if(iv->obufcnt >= cnt+8)
  1652.     {/* There is sufficient room in the current chunk */
  1653.     long size = ((long*)iv->obuf)[1];
  1654.       iv->obuf += size+8;
  1655.     }
  1656.     else
  1657.     {/* Allocate a new chunk of linked list space */
  1658.       iv->obufcnt = 4080;
  1659.       iv->obuf = Ccalloc(FUNCDATA, 1, iv->obufcnt);
  1660.     }
  1661.  
  1662.     *((void**)next) = iv->obuf;        /* link back to old entry */
  1663.     ((long*)iv->obuf)[1] = cnt;        /* record the size of the data */
  1664.     iv->obufcnt -= cnt+8;            /* deduct data size plus overhead */
  1665.     memcpy(&((long*)iv->obuf)[2], buf, cnt);  /* copy the data to this area */
  1666.     if(buf[0] != LINENO && buf[0] != NFUNC)
  1667.     {/* A line number record is an anomoly */
  1668.         if(iv->extmark)
  1669.             addto_extlist(iv, buf);        /* reference to external variable here */
  1670.         iv->func_offset += cnt;            /* increase the program counter */
  1671.     }
  1672.  
  1673.     iv->cod->ee = (struct _nodeOBUF *)iv->obuf;    /* points to obuf chunks */
  1674.     link_cod(iv);
  1675.  
  1676.     return iv->obuf;    /* return the address of this sub chunk */
  1677. }
  1678. static void
  1679. do_conversion(Piv iv, PND dst, PND src)
  1680. {
  1681. unsigned char obuf[2];
  1682. int dsize = dst->size;
  1683. int ssize = src->size;
  1684. unsigned char ddtype = dst->dtype;
  1685. unsigned char sdtype = src->dtype;
  1686. #define SRC(a) (a<<4)
  1687.  
  1688.     if(src->atype & (A_ABSOLUTE|A_POINTER|A_VALUE) == (A_POINTER|A_VALUE))
  1689.     {
  1690.         if(src->atype & A_DATA)
  1691.             obuf[0] = ABSMEM;
  1692.         else if(src->atype & (A_AUTO|A_PARAM))
  1693.             obuf[0] = ABSSTK;
  1694.         else
  1695.             PERROR(pName ":ERROR: Line:%d bad conversion0\n", iv->lastline);
  1696.         write_obuf(iv, obuf, 1);
  1697.         return;
  1698.     }
  1699.     obuf[0] = CVT;
  1700.     switch(ddtype)
  1701.     {
  1702.         case    D_SIGNED:            /* dest is signed integer */
  1703.         {
  1704.             if(dsize == 1)
  1705.                 obuf[1] = BYTE;
  1706.             else if(dsize == 2)
  1707.                 obuf[1] = SHORT;
  1708.             else if(dsize == 4)
  1709.                 obuf[1] = LONG;
  1710.             else if(dsize == 8)
  1711.                 obuf[1] = CLONGLONG;
  1712.             switch(sdtype)
  1713.             {
  1714.                 case D_SIGNED:
  1715.                 {/* src is signed integer */
  1716.                     if(dsize <= ssize)
  1717.                         return;
  1718.                     if(ssize == 1)
  1719.                         obuf[1] |= SRC(BYTE);
  1720.                     else if(ssize == 2)
  1721.                         obuf[1] |= SRC(SHORT);
  1722.                     else if(ssize == 4)
  1723.                         obuf[1] |= SRC(LONG);
  1724.                     else if(ssize == 8)
  1725.                         obuf[1] |= SRC(CLONGLONG);
  1726.                     break;
  1727.                 }
  1728.                 case D_UNSIGNED:
  1729.                 case D_SEGMENT:
  1730.                 {/* src is unsigned integer */
  1731.                     if(dsize <= ssize)
  1732.                         return;
  1733.                     if(ssize == 1)
  1734.                         obuf[1] |= SRC(UBYTE);
  1735.                     else if(ssize == 2)
  1736.                         obuf[1] |= SRC(USHORT);
  1737.                     else if(ssize == 4)
  1738.                         obuf[1] |= SRC(ULONG);
  1739.                     else if(ssize == 8)
  1740.                         obuf[1] |= SRC(CULONGLONG);
  1741.                     break;
  1742.                 }
  1743.                 case D_FLOAT:
  1744.                 {/* src is floating point */
  1745.                     if(ssize == 4)
  1746.                         obuf[1] |= SRC(FLOAT);
  1747.                     else if(ssize == 8)
  1748.                         obuf[1] |= SRC(DOUBLE);
  1749.                     else
  1750.                         obuf[1] |= SRC(CLONGDOUBLE);
  1751.                     break;
  1752.                 }
  1753.                 case D_POINTER:
  1754.                 case D_FUNCPTR:
  1755.                 {/* src is unsigned int */
  1756.                     if(dsize <= ssize)
  1757.                         return;
  1758.                     if(ssize == 1)
  1759.                         obuf[1] |= SRC(UBYTE);
  1760.                     else if(ssize == 2)
  1761.                         obuf[1] |= SRC(USHORT);
  1762.                     else if(ssize == 4)
  1763.                         obuf[1] |= SRC(ULONG);
  1764.                     else if(ssize == 8)
  1765.                         obuf[1] |= SRC(CULONGLONG);
  1766.                     break;
  1767.                 }
  1768.                 default:
  1769.                     PERROR(pName ":ERROR: Line:%d bad conversion1\n", iv->lastline);
  1770.             }
  1771.             break;
  1772.         }
  1773.         case    D_UNSIGNED:    /* dest is unsigned integer */
  1774.         case    D_SEGMENT:
  1775.         {
  1776.             if(dsize == 1)
  1777.                 obuf[1] = UBYTE;
  1778.             else if(dsize == 2)
  1779.                 obuf[1] = USHORT;
  1780.             else if(dsize == 4)
  1781.                 obuf[1] = ULONG;
  1782.             else if(dsize == 8)
  1783.                 obuf[1] = CULONGLONG;
  1784.             switch(sdtype)
  1785.             {
  1786.                 case D_SIGNED:
  1787.                 {/* src is signed integer */
  1788.                     if(dsize <= ssize)
  1789.                         return;
  1790.                     if(ssize == 1)
  1791.                         obuf[1] |= SRC(BYTE);
  1792.                     else if(ssize == 2)
  1793.                         obuf[1] |= SRC(SHORT);
  1794.                     else if(ssize == 4)
  1795.                         obuf[1] |= SRC(LONG);
  1796.                     else if(ssize == 8)
  1797.                         obuf[1] |= SRC(CLONGLONG);
  1798.                     break;
  1799.                 }
  1800.                 case D_UNSIGNED:
  1801.                 case D_SEGMENT:
  1802.                 {/* src is unsigned integer */
  1803.                     if(dsize <= ssize)
  1804.                         return;
  1805.                     if(ssize == 1)
  1806.                         obuf[1] |= SRC(UBYTE);
  1807.                     else if(ssize == 2)
  1808.                         obuf[1] |= SRC(USHORT);
  1809.                     else if(ssize == 4)
  1810.                         obuf[1] |= SRC(ULONG);
  1811.                     else if(ssize == 8)
  1812.                         obuf[1] |= SRC(CULONGLONG);
  1813.                     break;
  1814.                 }
  1815.                 case D_FLOAT:
  1816.                 {/* src is floating point */
  1817.                     if(ssize == 4)
  1818.                         obuf[1] |= SRC(FLOAT);
  1819.                     else if(ssize == 8)
  1820.                         obuf[1] |= SRC(DOUBLE);
  1821.                     else
  1822.                         obuf[1] |= SRC(CLONGDOUBLE);
  1823.                     break;
  1824.                 }
  1825.                 case D_POINTER:
  1826.                 case D_FUNCPTR:
  1827.                 {/* src is unsigned integer */
  1828.                     if(dsize <= ssize)
  1829.                         return;                    
  1830.                     if(ssize == 1)
  1831.                         obuf[1] |= SRC(UBYTE);
  1832.                     else if(ssize == 2)
  1833.                         obuf[1] |= SRC(USHORT);
  1834.                     else if(ssize == 4)
  1835.                         obuf[1] |= SRC(ULONG);
  1836.                     else if(ssize == 8)
  1837.                         obuf[1] |= SRC(CULONGLONG);
  1838.                     break;
  1839.                 }
  1840.                 default:
  1841.                     PERROR(pName ":ERROR: Line:%d bad conversion2\n", iv->lastline);
  1842.             }
  1843.             break;
  1844.         }
  1845.         case    D_FLOAT:    /* dest is float, double, long double */
  1846.         {
  1847.             if(dsize == 4)
  1848.                 obuf[1] = FLOAT;
  1849.             else if(dsize == 8)
  1850.                 obuf[1] = DOUBLE;
  1851.             else
  1852.                 obuf[1] = CLONGDOUBLE;
  1853.             switch(sdtype)
  1854.             {
  1855.                 case D_SIGNED:
  1856.                 {/* src is signed integer */
  1857.                     if(ssize == 1)
  1858.                         obuf[1] |= SRC(BYTE);
  1859.                     else if(ssize == 2)
  1860.                         obuf[1] |= SRC(SHORT);
  1861.                     else if(ssize == 4)
  1862.                         obuf[1] |= SRC(LONG);
  1863.                     else if(ssize == 8)
  1864.                         obuf[1] |= SRC(CLONGLONG);
  1865.                     break;
  1866.                 }
  1867.                 case D_UNSIGNED:
  1868.                 case D_SEGMENT:
  1869.                 {/* src is unsigned integer */
  1870.                     if(ssize == 1)
  1871.                         obuf[1] |= SRC(UBYTE);
  1872.                     else if(ssize == 2)
  1873.                         obuf[1] |= SRC(USHORT);
  1874.                     else if(ssize == 4)
  1875.                         obuf[1] |= SRC(ULONG);
  1876.                     else if(ssize == 8)
  1877.                         obuf[1] |= SRC(CULONGLONG);
  1878.                     break;
  1879.                 }
  1880.                 case D_FLOAT:
  1881.                 {/* src is floating point */
  1882.                     if(dsize == ssize)
  1883.                         return;
  1884.                     if(ssize == 4)
  1885.                         obuf[1] |= SRC(FLOAT);
  1886.                     else if(ssize == 8)
  1887.                         obuf[1] |= SRC(DOUBLE);
  1888.                     else
  1889.                         obuf[1] |= SRC(CLONGDOUBLE);
  1890.                     break;
  1891.                 }
  1892.                 case D_POINTER:
  1893.                 case D_FUNCPTR:
  1894.                 {/* src is unsigned integer */
  1895.                     if(ssize == 1)
  1896.                         obuf[1] |= SRC(UBYTE);
  1897.                     else if(ssize == 2)
  1898.                         obuf[1] |= SRC(USHORT);
  1899.                     else if(ssize == 4)
  1900.                         obuf[1] |= SRC(ULONG);
  1901.                     else if(ssize == 8)
  1902.                         obuf[1] |= SRC(CULONGLONG);
  1903.                     break;
  1904.                 }
  1905.                 default:
  1906.                     PERROR(pName ":ERROR: Line:%d bad conversion3\n", iv->lastline);
  1907.             }
  1908.             break;
  1909.         }
  1910.         case    D_POINTER:
  1911.         case    D_FUNCPTR:
  1912.         {/* dest is unsigned integer */
  1913.             if(dsize == 1)
  1914.                 obuf[1] = BYTE;
  1915.             else if(dsize == 2)
  1916.                 obuf[1] = SHORT;
  1917.             else if(dsize == 4)
  1918.                 obuf[1] = LONG;
  1919.             else if(dsize == 8)
  1920.                 obuf[1] = CLONGLONG;
  1921.             switch(sdtype)
  1922.             {
  1923.                 case D_SIGNED:
  1924.                 {/* src is signed integer */
  1925.                     if(dsize <= ssize)
  1926.                         return;
  1927.                     if(ssize == 1)
  1928.                         obuf[1] |= SRC(BYTE);
  1929.                     else if(ssize == 2)
  1930.                         obuf[1] |= SRC(SHORT);
  1931.                     else if(ssize == 4)
  1932.                         obuf[1] |= SRC(LONG);
  1933.                     else if(ssize == 8)
  1934.                         obuf[1] |= SRC(CLONGLONG);
  1935.                     break;
  1936.                 }
  1937.                 case D_UNSIGNED:
  1938.                 case D_SEGMENT:
  1939.                 {/* src is unsigned integer */
  1940.                     if(dsize <= ssize)
  1941.                         return;
  1942.                     if(ssize == 1)
  1943.                         obuf[1] |= SRC(UBYTE);
  1944.                     else if(ssize == 2)
  1945.                         obuf[1] |= SRC(USHORT);
  1946.                     else if(ssize == 4)
  1947.                         obuf[1] |= SRC(ULONG);
  1948.                     else if(ssize == 8)
  1949.                         obuf[1] |= SRC(CULONGLONG);
  1950.                     break;
  1951.                 }
  1952.                 case D_FLOAT:
  1953.                 {/* src is floating point */
  1954.                     if(ssize == 4)
  1955.                         obuf[1] |= SRC(FLOAT);
  1956.                     else if(ssize == 8)
  1957.                         obuf[1] |= SRC(DOUBLE);
  1958.                     else
  1959.                         obuf[1] |= SRC(CLONGDOUBLE);
  1960.                     break;
  1961.                 }
  1962.                 case D_POINTER:
  1963.                 case D_FUNCPTR:
  1964.                 {/* src is unsigned integer */
  1965.                     if(dsize <= ssize)
  1966.                         return;
  1967.                     if(ssize == 1)
  1968.                         obuf[1] |= SRC(UBYTE);
  1969.                     else if(ssize == 2)
  1970.                         obuf[1] |= SRC(USHORT);
  1971.                     else if(ssize == 4)
  1972.                         obuf[1] |= SRC(ULONG);
  1973.                     else if(ssize == 8)
  1974.                         obuf[1] |= SRC(CULONGLONG);
  1975.                     break;
  1976.                 }
  1977.                 default:
  1978.                     PERROR(pName ":ERROR: Line:%d bad conversion4\n", iv->lastline);
  1979.             }
  1980.             break;
  1981.         }
  1982.         default:
  1983.             PRINTF("Line:%d no conversion\n", iv->lastline);
  1984.             return;
  1985.     }
  1986.     write_obuf(iv, obuf, 2);
  1987. #undef SRC
  1988. }
  1989. static int
  1990. check_assignment_conversion(PND dst, PND src)
  1991. {
  1992. long dsize = dst->size;
  1993. long ssize = src->size;
  1994. unsigned char ddtype = dst->dtype;
  1995. unsigned char sdtype = src->dtype;
  1996. int ret = 0;
  1997.  
  1998.     if(src->atype & (A_ABSOLUTE|A_POINTER|A_VALUE) == (A_POINTER|A_VALUE))
  1999.         return 1;
  2000.     switch(ddtype)
  2001.     {
  2002.         case    D_SIGNED:            /* dest is signed integer */
  2003.         {
  2004.             switch(sdtype)
  2005.             {
  2006.                 case D_SIGNED:
  2007.                 case D_UNSIGNED:
  2008.                 case D_SEGMENT:
  2009.                 case D_POINTER:
  2010.                 case D_FUNCPTR:
  2011.                 {
  2012.                     if(dsize > ssize)
  2013.                         ret = 1;
  2014.                     break;
  2015.                 }
  2016.                 case D_FLOAT:
  2017.                 {
  2018.                     ret = 1;
  2019.                     break;
  2020.                 }
  2021.             }
  2022.             break;
  2023.         }
  2024.         case    D_UNSIGNED:    /* dest is unsigned integer */
  2025.         case    D_SEGMENT:
  2026.         {
  2027.             switch(sdtype)
  2028.             {
  2029.                 case D_SIGNED:
  2030.                 case D_UNSIGNED:
  2031.                 case D_SEGMENT:
  2032.                 case D_POINTER:
  2033.                 case D_FUNCPTR:
  2034.                 {
  2035.                     if(dsize > ssize)
  2036.                         ret = 1;
  2037.                     break;
  2038.                 }
  2039.                 case D_FLOAT:
  2040.                 {
  2041.                     ret = 1;
  2042.                     break;
  2043.                 }
  2044.             }
  2045.             break;
  2046.         }
  2047.         case    D_FLOAT:    /* dest is float, double, long double */
  2048.         {
  2049.             if(sdtype == D_FLOAT)
  2050.             {
  2051.                 if(dsize != ssize)
  2052.                     ret = 1;
  2053.             }
  2054.             else ret = 1;
  2055.             break;
  2056.         }
  2057.         case    D_POINTER:
  2058.         case    D_FUNCPTR:        /* dest is pointer */
  2059.         {
  2060.             switch(sdtype)
  2061.             {
  2062.                 case D_SIGNED:
  2063.                 case D_UNSIGNED:
  2064.                 case D_SEGMENT:
  2065.                 case D_POINTER:
  2066.                 case D_FUNCPTR:
  2067.                 {
  2068.                     if(dsize > ssize)
  2069.                         ret = 1;
  2070.                     break;
  2071.                 }
  2072.                 case D_FLOAT:
  2073.                 {
  2074.                     ret = 1;
  2075.                     break;
  2076.                 }
  2077.             }
  2078.             break;
  2079.         }
  2080.     }
  2081.     return ret;
  2082. }
  2083. static int
  2084. check_binop_conversion(PND dst, PND src)
  2085. {
  2086. long dsize = dst->size;
  2087. long ssize = src->size;
  2088. unsigned char ddtype = dst->dtype;
  2089. unsigned char sdtype = src->dtype;
  2090. int ret = 0;
  2091.  
  2092.     switch(ddtype)
  2093.     {
  2094.         case    D_SIGNED:            /* dest is signed integer */
  2095.         {
  2096.             switch(sdtype)
  2097.             {
  2098.                 case D_SIGNED:
  2099.                 case D_UNSIGNED:
  2100.                 case D_SEGMENT:
  2101.                 case D_POINTER:
  2102.                 case D_FUNCPTR:
  2103.                 {
  2104.                     if(dsize > ssize)
  2105.                         ret = 1;
  2106.                     break;
  2107.                 }
  2108.             }
  2109.             break;
  2110.         }
  2111.         case    D_UNSIGNED:    /* dest is unsigned integer */
  2112.         case    D_SEGMENT:
  2113.         {
  2114.             switch(sdtype)
  2115.             {
  2116.                 case D_SIGNED:
  2117.                 case D_UNSIGNED:
  2118.                 case D_SEGMENT:
  2119.                 case D_POINTER:
  2120.                 case D_FUNCPTR:
  2121.                 {
  2122.                     if(dsize > ssize)
  2123.                         ret = 1;
  2124.                     break;
  2125.                 }
  2126.             }
  2127.             break;
  2128.         }
  2129.         case    D_FLOAT:    /* dest is float, double, long double */
  2130.         {
  2131.             if(sdtype == D_FLOAT)
  2132.             {
  2133.                 if(dsize > ssize)
  2134.                     ret = 1;
  2135.             }
  2136.             else ret = 1;
  2137.             break;
  2138.         }
  2139.         case    D_POINTER:
  2140.         case    D_FUNCPTR:        /* dest is pointer */
  2141.         {
  2142.             switch(sdtype)
  2143.             {
  2144.                 case D_SIGNED:
  2145.                 case D_UNSIGNED:
  2146.                 case D_SEGMENT:
  2147.                 case D_POINTER:
  2148.                 case D_FUNCPTR:
  2149.                 {
  2150.                     if(dsize > ssize)
  2151.                         ret = 1;
  2152.                     break;
  2153.                 }
  2154.             }
  2155.             break;
  2156.         }
  2157.     }
  2158.     return ret;
  2159. }
  2160. static int
  2161. get_size(int type, int size)
  2162. {
  2163.     switch(type)
  2164.     {
  2165.         case    D_ARRAY:
  2166.         case    D_STRUCT:
  2167.         case    D_FUNCTION:
  2168.             return B4;
  2169.  
  2170.         default:
  2171.             switch(size)
  2172.             {
  2173.                 case 1:
  2174.                     return B1;
  2175.                 case 2:
  2176.                     return B2;
  2177.                 case 4:
  2178.                     return B4;
  2179.                 case 8:
  2180.                     return B8;
  2181.                 default:
  2182. #if SUPPORT_LONG_DOUBLE
  2183.                     return BX;
  2184. #endif
  2185.             }
  2186.     }
  2187.     return 0;
  2188. }
  2189. static int
  2190. load_addr(Piv iv, unsigned char *poc, void *buf, PND pnd, int shft)
  2191. {/* Use the shortest possible representation */
  2192. long offset = pnd->OFFSET;
  2193. long ofs = offset >> 2;
  2194.  
  2195.     if(pnd->atype & (A_EXTERN|A_ABSOLUTE))
  2196.     {/* 4 bytes for absolute values */
  2197.         *poc |= 3<<shft;
  2198.         *((long*)buf) = offset;
  2199.         iv->extmark += 1;
  2200.         iv->markedsym[iv->extmark] = pnd->SYMNUM;
  2201.         iv->markedbuf[iv->extmark] = buf;
  2202.         return 4;
  2203.     }
  2204.     if(offset & 0xff000000)
  2205.     {/* Relative values are restricted to 28 bits max */
  2206.         PERROR(pName ":ERROR: Line:%d offset too large %x\n", iv->lastline, ofs);
  2207.         return 0;
  2208.     }
  2209.     if(offset & 0xffff0000 || offset & 0x00000003)
  2210.     {/* 3 bytes for large values and non-aligned values */
  2211.         *poc |= 2<<shft;
  2212.         *((long*)buf) = offset;
  2213.         return 3;
  2214.     }
  2215.     else if(ofs & 0xffffff00)
  2216.     {/* 2 or fewer bytes for small aligned values */
  2217.         *poc |= 1<<shft;
  2218.         *((short*)buf) = (short)ofs;
  2219.         return 2;
  2220.     }
  2221.     else
  2222.     {
  2223.         *((char*)buf) = (char)ofs;
  2224.         return 1;
  2225.     }
  2226.  
  2227. }
  2228. static void
  2229. load_val(Piv iv, unsigned long val)
  2230. {
  2231. unsigned char obuf[10];
  2232.  
  2233.     obuf[0] = LUI;
  2234.     ++iv->stackdepth;
  2235.     if(val & 0xffff0000)
  2236.     {
  2237.         obuf[0] |= 2;
  2238.         *((unsigned long*)&obuf[1]) = val;
  2239.         write_obuf(iv, obuf, 5);
  2240.     }
  2241.     else if(val & 0xffffff00)
  2242.     {
  2243.         obuf[0] |= 1;
  2244.         *((unsigned short*)&obuf[1]) = (unsigned short)val;
  2245.         write_obuf(iv, obuf, 3);
  2246.     }
  2247.     else
  2248.     {
  2249.         obuf[1] = (unsigned char)val;
  2250.         write_obuf(iv, obuf, 2);
  2251.     }
  2252. }
  2253. static int
  2254. load_immed(Piv iv, unsigned char *poc, void *obuf, PND pnd, int osize)
  2255. {
  2256. unsigned short dtype = pnd->dtype;
  2257. unsigned char mosize = pnd->opsize;
  2258. void *ibuf = pnd->data;
  2259.  
  2260.     if(osize >= 0)
  2261.     {/* force the immediate value to conform to osize */
  2262.         if(osize == mosize)
  2263.         {
  2264.             switch(osize)
  2265.             {
  2266.                 case    B1:
  2267.                     *((char*)obuf) = *((char*)ibuf);
  2268.                     return 1;            
  2269.                 case    B2:
  2270.                     *((short*)obuf) = *((short*)ibuf);
  2271.                     return 2;
  2272.                 case    B4:
  2273.                     *((long*)obuf) = *((long*)ibuf);
  2274.                     return 4;
  2275.                 case    B8:
  2276.                     *((double*)obuf) = *((double*)ibuf);
  2277.                     return 8;
  2278.                 case    BX:
  2279. #if SUPPORT_LONG_DOUBLE
  2280.                     *((long double*)obuf) = *((long double*)ibuf);
  2281. #else
  2282.                     memcpy(obuf, ibuf, XSZ);
  2283. #endif
  2284.                     return XSZ;
  2285.                 default:
  2286.                     PERROR(pName ":ERROR: Line:%d LOAD IMMED SYSERR osize=%d\n", iv->lastline, osize);
  2287.             }
  2288.         }
  2289.         else /* osize != mosize */
  2290.         {
  2291.             if(dtype == D_FLOAT)
  2292.             {
  2293.             float f;
  2294.             double d;
  2295. #if SUPPORT_LONG_DOUBLE
  2296.             long double ld;
  2297. #endif
  2298.                 switch(osize)
  2299.                 {
  2300.                     case    B4:
  2301.                         switch(mosize)
  2302.                         {
  2303.                             case    B8:
  2304.                                 f = (float)*((double*)ibuf);
  2305.                                 *((float*)obuf) = f;
  2306.                                 return 4;
  2307.                             case    BX:
  2308. #if SUPPORT_LONG_DOUBLE
  2309.                                 f = (float)*((long double*)ibuf);
  2310.                                 *((float*)obuf) = f;
  2311.                                 return 4;
  2312. #else
  2313.                                 PERROR(pName ":ERROR: Line:%d long double conversion not supported\n", iv->lastline);
  2314. #endif
  2315.                             default:
  2316.                                 PERROR(pName ":ERROR: Line:%d bad floating immediate input\n",iv->lastline);
  2317.                         }
  2318.                     case    B8:
  2319.                         switch(mosize)
  2320.                         {
  2321.                             case    B4:
  2322.                                 d = (double)*((float*)ibuf);
  2323.                                 *((double*)obuf) = d;
  2324.                                 return 8;
  2325.                             case    BX:
  2326. #if SUPPORT_LONG_DOUBLE
  2327.                                 d = (double)*((long double*)ibuf);
  2328.                                 *((double*)obuf) = d;
  2329.                                 return 8;
  2330. #else
  2331.                                 PERROR(pName ":ERROR: Line:%d long double conversion not supported\n", iv->lastline);
  2332. #endif
  2333.                             default:
  2334.                                 PERROR(pName ":ERROR: Line:%d bad floating immediate input\n", iv->lastline);
  2335.                         }
  2336.                     case    BX:
  2337. #if SUPPORT_LONG_DOUBLE
  2338.                         switch(mosize)
  2339.                         {
  2340.                             case    B4:
  2341.                                 ld = (long double)*((float*)ibuf);
  2342.                                 *((long double*)obuf) = ld;
  2343.                                 return XSZ;
  2344.                             case    B8:
  2345.                                 ld = (long double)*((double*)ibuf);
  2346.                                 *((long double*)obuf) = ld;
  2347.                                 return XSZ;
  2348.                             default:
  2349.                                 PERROR(pName ":ERROR: Line:%d bad floating immediate input\n", iv->lastline);
  2350.                         }
  2351.                         break;
  2352. #else
  2353.                         PERROR(pName ":ERROR: Line:%d long double conversion not supported\n", iv->lastline);
  2354. #endif
  2355.                         break;
  2356.                     default:
  2357.                         PERROR(pName ":ERROR: Line:%d bad floating immediate output\n", iv->lastline);
  2358.                 }
  2359.             }/* END: dtype == D_FLOAT */
  2360.             else if(dtype == D_UNSIGNED || dtype == D_POINTER)
  2361.             {
  2362.                 switch(osize)
  2363.                 {
  2364.                     case B1:
  2365.                         *((unsigned char*)obuf) = *((unsigned char *)ibuf);
  2366.                         return 1;
  2367.                     case B2:
  2368.                         switch(mosize)
  2369.                         {
  2370.                             case B1:
  2371.                                 *((unsigned short*)obuf) = *((unsigned char*)ibuf);
  2372.                                 return 2;
  2373.                             case B4:
  2374.                             case B8:
  2375.                                 *((unsigned short*)obuf) = *((unsigned short*)ibuf);
  2376.                                 return 2;
  2377.                             case BX:
  2378.                                 PERROR(pName ":ERROR: Line:%d invalid integer size\n", iv->lastline);
  2379.                             default:
  2380.                                 PERROR(pName ":ERROR: Line:%d invalid immediate input\n", iv->lastline);
  2381.                         }
  2382.                     case B4:
  2383.                         switch(mosize)
  2384.                         {
  2385.                             case B1:
  2386.                                 *((unsigned long*)obuf) = *((unsigned char*)ibuf);
  2387.                                 return 4;
  2388.                             case B2:
  2389.                                 *((unsigned long*)obuf) = *((unsigned short*)ibuf);
  2390.                                 return 4;
  2391.                             case B8:
  2392.                                 *((unsigned long*)obuf) = *((unsigned long*)ibuf);
  2393.                                 return 4;
  2394.                             case BX:
  2395.                                 PERROR(pName ":ERROR: Line: invalid integer size\n", iv->lastline);
  2396.                             default:
  2397.                                 PERROR(pName ":ERROR: Line:%d invalid immediate input\n", iv->lastline);
  2398.                         }
  2399.                     case B8:
  2400.                     {
  2401.                     unsigned long l[2];
  2402.                         l[0] = 0;
  2403.                         l[1] = 0;
  2404.                         if(mosize == B4)
  2405.                             l[0] = *((unsigned long*)ibuf);
  2406.                         else if(mosize == B2)
  2407.                             l[0] = *((unsigned short*)ibuf);
  2408.                         else if(mosize == B1)
  2409.                             l[0] = *((unsigned char*)ibuf);
  2410.                         else
  2411.                             PERROR(pName ":ERROR: Line:%d invalid integer size\n", iv->lastline);
  2412.                         memcpy(obuf, l, 8);
  2413.                         return 8;
  2414.                     }
  2415.                     default:
  2416.                     PERROR(pName ":ERROR: Line:%d invalid integer size=%d\n",
  2417.                             iv->lastline, osize);
  2418.                 }
  2419.             }
  2420.             else /* signed integer */
  2421.             {
  2422.                 switch(osize)
  2423.                 {
  2424.                     case B1:
  2425.                         *((char*)obuf) = *((char *)ibuf);
  2426.                         return 1;
  2427.                     case B2:
  2428.                         switch(mosize)
  2429.                         {
  2430.                             case B1:
  2431.                                 *((short*)obuf) = *((char*)ibuf);
  2432.                                 return 2;
  2433.                             case B4:
  2434.                             case B8:
  2435.                                 *((short*)obuf) = *((short*)ibuf);
  2436.                                 return 2;
  2437.                             case BX:
  2438.                                 PERROR(pName ":ERROR: Line:%d invalid integer size\n", iv->lastline);
  2439.                             default:
  2440.                                 PERROR(pName ":ERROR: Line:%d invalid immediate input\n",iv->lastline);
  2441.                         }
  2442.                     case B4:
  2443.                         switch(mosize)
  2444.                         {
  2445.                             case B1:
  2446.                                 *((long*)obuf) = *((char*)ibuf);
  2447.                                 return 4;
  2448.                             case B2:
  2449.                                 *((long*)obuf) = *((short*)ibuf);
  2450.                                 return 4;
  2451.                             case B8:
  2452.                                 *((long*)obuf) = *((long*)ibuf);
  2453.                                 return 4;
  2454.                             case BX:
  2455.                                 PERROR(pName ":ERROR: Line:%d invalid integer size\n", iv->lastline);
  2456.                             default:
  2457.                                 PERROR(pName ":ERROR: Line:%d invalid immediate input\n", iv->lastline);
  2458.                         }
  2459.                     case B8:
  2460.                     {
  2461.                     long l[2];
  2462.                         l[0] = 0;
  2463.                         l[1] = 0;
  2464.                         if(mosize == B4)
  2465.                             l[0] = *((long*)ibuf);
  2466.                         else if(mosize == B2)
  2467.                             l[0] = *((short*)ibuf);
  2468.                         else if(mosize == B1)
  2469.                             l[0] = *((char*)ibuf);
  2470.                         else
  2471.                             PERROR(pName ":ERROR: Line:%d invalid integer size\n", iv->lastline);
  2472.                         if(l[0] < 0)
  2473.                             l[1] = -1;
  2474.                         memcpy(obuf, l, 8);
  2475.                         return 8;
  2476.                     }
  2477.                     default:
  2478.                       PERROR(pName ":ERROR: Line:%d invalid integer size=%d\n",
  2479.                           iv->lastline, osize);
  2480.                 }
  2481.             }/* END: signed integer */
  2482.         }/* END: osize != mosize */
  2483.         /* NOT REACHED */
  2484.         PERROR(pName ":ERROR: Line:%d LOAD IMMED SYSERR1 osize=%d mosize=%d\n", iv->lastline, osize, mosize);
  2485.         return 0; /* suppress compiler warning */
  2486.     }
  2487.     else
  2488.     {/* generate the shortest possible immediate value */
  2489.     int thesize = 0;
  2490.         if(dtype == D_FLOAT)
  2491.         {
  2492.             switch(mosize)
  2493.             {
  2494.                 case    B4:
  2495.                     *((float*)obuf) = *((float*)ibuf);
  2496.                     thesize = 4;
  2497.                     break;
  2498.                 case    B8:
  2499.                     *((double*)obuf) = *((double*)ibuf);
  2500.                     thesize = 8;
  2501.                     break;
  2502.                 case    BX:
  2503. #if SUPPORT_LONG_DOUBLE
  2504.                     *((long double*)obuf) = *((long double*)ibuf);
  2505. #else
  2506.                     memcpy(obuf, ibuf, XSZ);
  2507. #endif
  2508.                     thesize = XSZ;
  2509.                     break;
  2510.                 default:
  2511.                     PERROR(pName ":ERROR: Line:%d wrong sized floating immediate\n", iv->lastline);
  2512.             }
  2513.         }
  2514.         else /* dtype not D_FLOAT */
  2515.         {
  2516.         int negative;
  2517.         int sgned;
  2518.         unsigned long ul[2];
  2519.         long *sl;
  2520.  
  2521.             ul[1] = 0;        
  2522.             negative = 0;
  2523.             sl = ul;
  2524.             if(dtype == D_UNSIGNED || dtype == D_POINTER)
  2525.             {
  2526.                 sgned = 0;
  2527.                 if(mosize == B8)
  2528.                 {
  2529.                     ul[0] = *((unsigned long*)ibuf);
  2530.                     ul[1] = *((unsigned long*)(((char*)ibuf)+4));
  2531.                 }
  2532.                 else
  2533.                 {
  2534.                     if(mosize == B4)
  2535.                         ul[0] = *((unsigned long*)ibuf);
  2536.                     else if(mosize == B2)
  2537.                         ul[0] = *((unsigned short*)ibuf);
  2538.                     else if(mosize == B1)
  2539.                         ul[0] = *((unsigned char*)ibuf);
  2540.                     else
  2541.                         PERROR(pName ":ERROR: Line:%d invalid integer immediate\n", iv->lastline);
  2542.                 }
  2543.             }
  2544.             else /* sgned */
  2545.             {
  2546.                 sgned = 1;
  2547.                 if(mosize == B8)
  2548.                 {
  2549.                     sl[0] = *((long*)ibuf);
  2550.                     sl[1] = *((long*)(((char*)ibuf)+4));
  2551.                     if(sl[1] < 0)
  2552.                     {
  2553.                         negative = 1;
  2554.                         ul[1] = ~ul[1];
  2555.                         ul[0] = ~ul[0];
  2556.                         if(ul[0] == 0xffffffff)
  2557.                         {
  2558.                             ul[0] = 0;
  2559.                             ul[1] += 1;
  2560.                         }
  2561.                         else ul[0] += 1;
  2562.                     }
  2563.                 }
  2564.                 else
  2565.                 {
  2566.                     if(mosize == B4)
  2567.                         sl[0] = *((long*)ibuf);
  2568.                     else if(mosize == B2)
  2569.                         sl[0] = *((short*)ibuf);
  2570.                     else if(mosize == B1)
  2571.                         sl[0] = *((char*)ibuf);
  2572.                     else
  2573.                         PERROR(pName ":ERROR: Line:%d invalid integer immediate\n",iv->lastline);
  2574.                     if(sl[0] < 0)
  2575.                     {
  2576.                         negative = 1;
  2577.                         sl[0] = -sl[0];
  2578.                     }
  2579.                 }
  2580.             } /* END: sgned */
  2581.             if(negative)
  2582.             {
  2583.                 if(ul[1])
  2584.                     mosize = B8;
  2585.                 else if(ul[0] & 0xffff8000)
  2586.                     mosize = B4;
  2587.                 else if(ul[0] & 0xffffff80)
  2588.                     mosize = B2;
  2589.                 else
  2590.                     mosize = B1;
  2591.             }
  2592.             else
  2593.             {
  2594.                 if(sgned)
  2595.                 {
  2596.                     if(ul[1])
  2597.                         mosize = B8;
  2598.                     else if(ul[0] & 0xffff8000)
  2599.                     {
  2600.                         if(!(ul[0] & 0xffff0000))
  2601.                         {
  2602.                             *poc = LUI;
  2603.                             mosize = B2;
  2604.                         }
  2605.                         else
  2606.                             mosize = B4;
  2607.                     }
  2608.                     else if(ul[0] & 0xffffff80)
  2609.                     {
  2610.                         if(!(ul[0] & 0xffffff00))
  2611.                         {
  2612.                             *poc = LUI;
  2613.                             mosize = B1;
  2614.                         }
  2615.                         else
  2616.                             mosize = B2;
  2617.                     }
  2618.                     else
  2619.                         mosize = B1;
  2620.                 }
  2621.                 else /* unsigned */
  2622.                 {
  2623.                     if(ul[1])
  2624.                         mosize = B8;
  2625.                     else if(ul[0] & 0xffff0000)
  2626.                         mosize = B4;
  2627.                     else if(ul[0] & 0xffffff00)
  2628.                         mosize = B2;
  2629.                     else
  2630.                         mosize = B1;
  2631.                 }
  2632.             }
  2633.             if(negative)
  2634.             {
  2635.                 ul[1] = ~ul[1];
  2636.                 ul[0] = ~ul[0];
  2637.                 if(ul[0] == 0xffffffff)
  2638.                 {
  2639.                     ul[0] = 0;
  2640.                     ul[1] += 1;
  2641.                 }
  2642.                 else ul[0] += 1;
  2643.             }
  2644.             switch(mosize)
  2645.             {
  2646.                 case B1:
  2647.                     *((char*)obuf) = *((char*)sl);
  2648.                     thesize = 1;
  2649.                     break;
  2650.                 case B2:
  2651.                     *((short*)obuf) = *((short*)sl);
  2652.                     thesize = 2;
  2653.                     break;
  2654.                 case B4:
  2655.                     *((long*)obuf) = *((long*)sl);
  2656.                     thesize = 4;
  2657.                     break;
  2658.                 case B8:
  2659.                     *((double*)obuf) = *((double*)sl);
  2660.                     thesize = 8;
  2661.                     break;
  2662.             }
  2663.         }/* END: not D_FLOAT */
  2664.         *poc |= mosize;
  2665.         return thesize;
  2666.     }
  2667. }
  2668. static void
  2669. addr_toevalstack(Piv iv, PND pnd)
  2670. {
  2671. unsigned char obuf[20];
  2672. int atype = pnd->atype;
  2673.  
  2674.     if(atype & (A_AUTO|A_PARAM|A_DATA))
  2675.     {
  2676.     int l;
  2677.         obuf[0] = LAI;
  2678.         l = 1;
  2679.         l += load_addr(iv, &obuf[0], &obuf[1], pnd, 0);
  2680.  
  2681.         write_obuf(iv, obuf, l);
  2682.         if(atype & (A_AUTO|A_PARAM))
  2683.         {
  2684.             obuf[0] = ABSSTK;
  2685.             write_obuf(iv, obuf, 1);
  2686.         }
  2687.         else if(l < 5)
  2688.         {
  2689.             obuf[0] = ABSMEM;
  2690.             write_obuf(iv, obuf, 1);
  2691.         }
  2692.         ++iv->stackdepth;
  2693.     }
  2694. }
  2695. static void
  2696. data_toevalstack(Piv iv, PND pnd, PND dst)
  2697. {
  2698. unsigned char obuf[20];
  2699. int xtra, oc;
  2700. unsigned short dtype, atype;
  2701. unsigned char osize;
  2702.  
  2703.         atype = pnd->atype;
  2704.         dtype = pnd->dtype;
  2705.         if(atype & A_IMMED)
  2706.         {
  2707.             if(dtype == D_UNSIGNED)
  2708.                 obuf[0] = LUI;
  2709.             else
  2710.                 obuf[0] = LI;
  2711.             xtra = load_immed(iv, &obuf[0], &obuf[1], pnd, -1);
  2712.             write_obuf(iv, obuf, 1+xtra);
  2713.             ++iv->stackdepth;
  2714.             return;
  2715.         }
  2716.         xtra = oc = 0;
  2717.         osize = pnd->opsize;
  2718.         if(osize == BX)
  2719.         {
  2720.             obuf[0] = XTD;
  2721.             osize = 0;
  2722.             oc = 1;
  2723.             xtra = 1;
  2724.         }
  2725.         if(atype & (A_TEMP|A_RET))
  2726.         {
  2727.             if(atype & A_MEMADDR)
  2728.             {
  2729.             unsigned char xsize = get_datasize(0, pnd);
  2730.                 if(osize == B8 && dtype < D_FLOAT)
  2731.                     obuf[xtra++] = XTD;
  2732.  
  2733.                 if(        dst    
  2734.                     &&    (pnd->TMPNUM == dst->TMPNUM)
  2735.                     &&    ((dst->atype & (A_ABSOLUTE|A_MEMADDR))
  2736.                             == (A_ABSOLUTE|A_MEMADDR))
  2737.                   )
  2738.                 {/* generally used for a += b etc. */
  2739.                     obuf[xtra++] = IMMED;
  2740.                     obuf[xtra] = DEREF1|xsize;
  2741.                     write_obuf(iv, obuf, 1+xtra);
  2742.                     ++iv->stackdepth;
  2743.                 }
  2744.                 else
  2745.                 {
  2746.                     obuf[xtra++] = IMMED;
  2747.                     obuf[xtra] = DEREF|get_datasize(0, pnd);
  2748.                     write_obuf(iv, obuf, 1+xtra);
  2749.                 }
  2750.                 pnd->atype &= ~A_MEMADDR;
  2751.                 pnd->atype |= A_VALUE;
  2752.             }
  2753.             return;
  2754.         }
  2755.  
  2756.         if(atype & (A_AUTO|A_PARAM))
  2757.         {
  2758.             if(atype & (A_POINTER|A_VALUE) == (A_POINTER|A_VALUE))
  2759.             {/* Put address on eval stack */
  2760.                 addr_toevalstack(iv, pnd);
  2761.                 pnd->atype |= A_ABSOLUTE;
  2762.                 return;
  2763.             }
  2764.             else
  2765.             {
  2766.                 obuf[oc] = LS|osize;
  2767.                 xtra += load_addr(iv, &obuf[oc], &obuf[oc+1], pnd, 2);
  2768.                 ++iv->stackdepth;
  2769.             }
  2770.         }
  2771.         else if(atype & A_DATA)
  2772.         {
  2773.             if(atype & (A_POINTER|A_VALUE) == (A_POINTER|A_VALUE))
  2774.             {/* Put address on eval stack */
  2775.                 addr_toevalstack(iv, pnd);
  2776.                 pnd->atype |= A_ABSOLUTE;
  2777.                 return;
  2778.             }
  2779.             else
  2780.             {
  2781.                 obuf[oc] = LM|osize;
  2782.                 xtra += load_addr(iv,&obuf[oc], &obuf[oc+1], pnd, 2);
  2783.                 ++iv->stackdepth;
  2784.             }
  2785.         }
  2786.         write_obuf(iv, obuf, 1+xtra);
  2787. }
  2788. static void
  2789. promote_arg(Piv iv, PND pnd, long argsize)
  2790. {
  2791. long dsize = pnd->size;
  2792. struct _nd dst;
  2793.  
  2794.     if(dsize != argsize)
  2795.     {
  2796.         dst.size = argsize;
  2797.         dst.dtype = pnd->dtype;
  2798.         dst.atype = 0;
  2799.         do_conversion(iv, &dst, pnd);
  2800.     }
  2801. }
  2802. static unsigned char
  2803. arg_toevalstack(Piv iv, PND pnd, long argsize)
  2804. {
  2805. unsigned char dtype;
  2806.  
  2807.     if(pnd->atype & A_IMMED)
  2808.     {
  2809.         data_toevalstack(iv, pnd, 0);
  2810.         return ARG;
  2811.     }
  2812.     dtype = pnd->dtype;
  2813.     if(dtype == D_STRUCT)
  2814.     {
  2815.         addr_toevalstack(iv, pnd);
  2816.         return ARGA;
  2817.     }
  2818.     else if(dtype == D_FUNCTION)
  2819.     {
  2820.         addr_toevalstack(iv, pnd);
  2821.         return ARGF;
  2822.     }
  2823.     else if(dtype == D_FUNCPTR)
  2824.     {
  2825.         data_toevalstack(iv, pnd, 0);
  2826.         return ARGF;
  2827.     }
  2828.     else if(dtype == D_ARRAY)
  2829.     {
  2830.         addr_toevalstack(iv, pnd);
  2831.     }
  2832.     else
  2833.     {
  2834.         data_toevalstack(iv, pnd, 0);
  2835.         promote_arg(iv, pnd, argsize);
  2836.     }
  2837.     return ARG;
  2838. }
  2839. static void
  2840. mov_esdata(Piv iv, unsigned short atype, int size)
  2841. {
  2842. unsigned char obuf[2];
  2843.  
  2844.     if(atype & A_MEMADDR)
  2845.     {
  2846.         if(size == B1)
  2847.             obuf[0] = MOVAA1;
  2848.         else if(size == B2)
  2849.             obuf[0] = MOVAA2;
  2850.         else if(size == B4)
  2851.             obuf[0] = MOVAA4;
  2852.         else if(size == B8)
  2853.             obuf[0] = MOVAA8;
  2854. #if SUPPORT_LONG_DOUBLE
  2855.         else if(size == BX)
  2856.             obuf[0] = MOVAAX;
  2857. #endif
  2858.         else {obuf[0] = MOVAAC; size = XSZ;}
  2859.     }
  2860.     else
  2861.     {
  2862.         if(size == B1)
  2863.             obuf[0] = MOVDA1;
  2864.         else if(size == B2)
  2865.             obuf[0] = MOVDA2;
  2866.         else if(size == B4)
  2867.             obuf[0] = MOVDA4;
  2868.         else if(size == B8)
  2869.             obuf[0] = MOVDA8;
  2870. #if SUPPORT_LONG_DOUBLE
  2871.         else if(size == BX)
  2872.             obuf[0] = MOVDAX;
  2873. #endif
  2874.         else
  2875.             PERROR(pName ":ERROR: Line:%d illegal mov data size=%d\n", iv->lastline, size);
  2876.     }
  2877.     if(obuf[0] == MOVAAC)
  2878.     {
  2879.         load_val(iv, size);
  2880.         --iv->stackdepth;
  2881.     }
  2882.     write_obuf(iv, obuf, 1);    
  2883.     iv->stackdepth -= 2;
  2884. }
  2885. static void
  2886. from_evalstack(Piv iv, PND d, PND s)
  2887. {
  2888. unsigned char obuf[20];
  2889. int xtra, oc;
  2890. unsigned short datype = d->atype;
  2891. unsigned char osize = d->opsize;
  2892.  
  2893.     xtra = oc = 0;
  2894.  
  2895.     if(datype & (A_TEMP|A_RET))
  2896.     {
  2897.         if(datype & A_MEMADDR)
  2898.         {
  2899.             mov_esdata(iv, s->atype, osize);
  2900.         }
  2901.         return;
  2902.     }
  2903.  
  2904.     if(osize == BX)
  2905.     {
  2906.         obuf[0] = XTD;
  2907.         oc = 1;
  2908.         osize = 0;
  2909.         xtra = 1;
  2910.     }
  2911.     if(datype & (A_AUTO|A_PARAM))
  2912.     {
  2913.         obuf[oc] = SS|osize;
  2914.         xtra += load_addr(iv, &obuf[oc], &obuf[oc+1], d, 2);
  2915.         --iv->stackdepth;
  2916.     }
  2917.     else if(datype & OPDATA)
  2918.     {
  2919.         obuf[oc] = SM|osize;
  2920.         xtra += load_addr(iv, &obuf[oc], &obuf[oc+1], d, 2);
  2921.         --iv->stackdepth;
  2922.     }
  2923.     write_obuf(iv, obuf, 1+xtra);
  2924. }
  2925. static unsigned char
  2926. get_datasize(unsigned char opcode, PND pnd)
  2927. {
  2928. unsigned char dtype = pnd->dtype;
  2929. long dsize = pnd->size;
  2930.  
  2931.     switch(dtype)
  2932.     {
  2933.         case    D_ARRAY:
  2934.         case    D_FUNCTION:
  2935.         case    D_STRUCT:
  2936.             return LONG;
  2937.     }
  2938.  
  2939.     if(        opcode == orop
  2940.         ||    opcode == andop
  2941.         ||    opcode == notop
  2942.         ||    opcode == lshop
  2943.         ||    opcode == complop
  2944.         ||    opcode == xorop
  2945.         )
  2946.     {
  2947.         if(dsize == 1)
  2948.             return B1;
  2949.         else if(dsize == 2)
  2950.             return B2;
  2951.         else if(dsize == 4)
  2952.             return B4;
  2953.         else if(dsize == 8)
  2954.             return B8;        
  2955.         else
  2956.             return BX;
  2957.     }
  2958.     else
  2959.     {
  2960.         if(dtype == D_UNSIGNED)
  2961.         {
  2962.             if(dsize == 1)
  2963.                 return UBYTE;
  2964.             else if(dsize == 2)
  2965.                 return USHORT;
  2966.             else if(dsize == 4)
  2967.                 return ULONG;
  2968.             else
  2969.             {
  2970.                 if(opcode == rshop)
  2971.                     return SULONGLONG;
  2972.                 return ULONGLONG;
  2973.             }
  2974.         }
  2975.         else if(dtype == D_FLOAT)
  2976.         {
  2977.             if(dsize == 4)
  2978.                 return FLOAT;
  2979.             else if(dsize == 8)
  2980.                 return DOUBLE;
  2981.             else
  2982.                 return LONGDOUBLE;
  2983.         }
  2984.         else
  2985.         {
  2986.             if(dsize == 1)
  2987.                 return BYTE;
  2988.             else if(dsize == 2)
  2989.                 return SHORT;
  2990.             else if(dsize == 4)
  2991.                 return LONG;
  2992.             else
  2993.             {
  2994.                 if(opcode == rshop)
  2995.                     return SLONGLONG;
  2996.                 return LONGLONG;
  2997.             }
  2998.         }
  2999.     }
  3000.     return 0;
  3001. }
  3002. static void *
  3003. new_nodeO(Piv iv)
  3004. {
  3005. PNODEO p;
  3006.  
  3007.     if(iv->ob_bufcnt < sizeof(NODEO))
  3008.     {/* Allocate a new chunk of linked list space */
  3009.       iv->ob_bufcnt = 4080;
  3010.       iv->ob_buf = Ccalloc(FUNCDATA, 1, iv->ob_bufcnt);
  3011.     }
  3012.     p = (PNODEO)iv->ob_buf;
  3013.     iv->ob_buf += sizeof(NODEO);
  3014.     iv->ob_bufcnt -= sizeof(NODEO);
  3015.     return p;    
  3016. }
  3017. static void
  3018. link_ob(Piv iv)
  3019. {/* Attach to the used list */
  3020.  
  3021.     if(!iv->ob_usedhead)
  3022.     {
  3023.         iv->ob_usedhead = iv->ob;
  3024.         iv->ob_usedtail = iv->ob;
  3025.     }
  3026.     else
  3027.     {
  3028.         iv->ob_usedtail->next = iv->ob;
  3029.         iv->ob_usedtail = iv->ob;
  3030.     }
  3031.     iv->ob = new_nodeO(iv);
  3032. }
  3033. static void *
  3034. new_nodeC(Piv iv)
  3035. {
  3036. PNODEC p;
  3037.  
  3038.     if(iv->cod_bufcnt < sizeof(NODEC))
  3039.     {/* Allocate a new chunk of linked list space */
  3040.       iv->cod_bufcnt = 4080;
  3041.       iv->cod_buf = Ccalloc(FUNCDATA, 1, iv->cod_bufcnt);
  3042.     }
  3043.     p = (PNODEC)iv->cod_buf;
  3044.     iv->cod_buf += sizeof(NODEC);
  3045.     iv->cod_bufcnt -= sizeof(NODEC);
  3046.     return p;    
  3047. }
  3048. static void
  3049. link_cod(Piv iv)
  3050. {/* Attach to the used list */
  3051.  
  3052.     if(!iv->cod_usedhead)
  3053.     {
  3054.         iv->cod_usedhead = iv->cod;
  3055.         iv->cod_usedtail = iv->cod;
  3056.     }
  3057.     else
  3058.     {
  3059.         iv->cod_usedtail->next = iv->cod;
  3060.         iv->cod_usedtail = iv->cod;
  3061.     }
  3062.     iv->cod = new_nodeC(iv);
  3063. }
  3064. static PNODEC
  3065. gen_inst(Piv iv, PNODEO pnode)
  3066. {
  3067. unsigned char *p;
  3068. unsigned char obuf[40];
  3069. int xtra, oc;
  3070. unsigned char opcode;
  3071. PND d,l,r;
  3072.  
  3073.     d = &pnode->d;
  3074.     l = &pnode->l;
  3075.     r = &pnode->r;
  3076.     p = pnode->p;
  3077.     opcode = *p;
  3078.  
  3079.     xtra = oc = 0;
  3080.     
  3081.     switch(opcode)
  3082.     {
  3083.         case regainop:
  3084.             obuf[0] = REGAIN;
  3085.             write_obuf(iv, obuf, 1);
  3086.             ++iv->stackdepth;
  3087.             break;
  3088.         case grabop:
  3089.             obuf[0] = SWAP4DEEP;
  3090.             write_obuf(iv, obuf, 1);
  3091.             break;
  3092.         case getvalop:
  3093.         case derefop:
  3094.         case assignop:
  3095.         case duptmpop:
  3096.         {
  3097.             if(        opcode == getvalop 
  3098.                 &&    !(l->atype & A_IMMED)
  3099.                 &&  l->dtype == D_FUNCTION)
  3100.             {
  3101.                 addr_toevalstack(iv, l);
  3102.             }
  3103.             else if(    opcode != derefop 
  3104.                     &&    !(l->atype & A_IMMED)
  3105.                     && check_assignment_conversion(d, l))
  3106.             {/* Must move data through evaluation stack */
  3107.                 data_toevalstack(iv, l, d);
  3108.                 do_conversion(iv, d, l);
  3109.                 l->atype &= ~A_MEMADDR;
  3110.                 l->atype |= A_VALUE;
  3111.                 if(opcode == assignop)
  3112.                   from_evalstack(iv, d, l);
  3113.             }
  3114.             else
  3115.             {/* Can move data directly from memory to memory */
  3116.             unsigned char ddtype = d->dtype;
  3117.             unsigned char osize = d->opsize;
  3118.             unsigned short latype = l->atype;
  3119.             unsigned short datype = d->atype;
  3120.                 if(osize == BX)
  3121.                 {
  3122.                     obuf[0] = XTD;
  3123.                     oc = 1;
  3124.                     osize = 0;
  3125.                     xtra = 1;
  3126.                 }
  3127.                 if(latype & A_IMMED)
  3128.                 {
  3129.                     if(datype & (A_TEMP|A_RET))
  3130.                     {
  3131.                         if(l->dtype == D_UNSIGNED)
  3132.                             obuf[oc] = LUI;
  3133.                         else
  3134.                             obuf[oc] = LI;
  3135.                         xtra += load_immed(iv, &obuf[oc], &obuf[oc+1], l, -1);
  3136.                         ++iv->stackdepth;
  3137.                         if(datype & A_MEMADDR)
  3138.                         {
  3139.                             write_obuf(iv, obuf, 1+xtra);
  3140.                             mov_esdata(iv, 0, osize);
  3141.                             break;
  3142.                         }
  3143.                     }
  3144.                     else if(datype & (A_AUTO|A_PARAM))
  3145.                     {
  3146.                     int lx;
  3147.                         obuf[0] = IMMED;
  3148.                         oc = 1;
  3149.                         xtra = 1;
  3150.                         obuf[oc] = SSI|osize;
  3151.                         lx = load_addr(iv, &obuf[oc], &obuf[oc+1], d, 2);
  3152.                         lx += load_immed(iv, &obuf[oc], &obuf[oc+1+lx], l, osize);
  3153.                         xtra += lx;
  3154.                     }
  3155.                     else if(datype & A_DATA)
  3156.                     {
  3157.                     int lx;
  3158.                         obuf[0] = IMMED;
  3159.                         oc = 1;
  3160.                         xtra = 1;
  3161.                         obuf[oc] = SMI|osize;
  3162.                         lx = load_addr(iv, &obuf[oc], &obuf[oc+1], d, 2);
  3163.                         lx += load_immed(iv, &obuf[oc], &obuf[oc+1+lx], l, osize);
  3164.                         xtra += lx;
  3165.                     }
  3166.                     else
  3167.                     {
  3168.                         return iv->cod_usedtail;
  3169.                     }
  3170.                 }
  3171.                 else if(latype & (A_TEMP|A_RET))
  3172.                 {
  3173.                     if(datype & (A_TEMP|A_RET))
  3174.                     {
  3175.                         if(opcode == duptmpop)
  3176.                         {
  3177.                             if(osize <= B4)
  3178.                                 obuf[0] = DUP4;
  3179.                             else
  3180.                                 obuf[0] = DUP;
  3181.                             xtra = 0;
  3182.                             ++iv->stackdepth;
  3183.                         }
  3184.                         else if(opcode == getvalop || opcode == derefop)
  3185.                         {
  3186.                             if(latype & A_MEMADDR)
  3187.                             {
  3188.                             unsigned char xsize = get_datasize(0, l);
  3189.                                 if(osize == B8 && ddtype < D_FLOAT)
  3190.                                     obuf[xtra++] = XTD;
  3191.                                 if(datype & A_MEMADDR)
  3192.                                     xsize = ULONG;
  3193.                                 obuf[xtra++] = IMMED;
  3194.                                 obuf[xtra] = DEREF|xsize;
  3195.                             }
  3196.                             else return iv->cod_usedtail;    /* nop */
  3197.                         }
  3198.                         else if(datype & A_MEMADDR)
  3199.                         {
  3200.                             mov_esdata(iv, latype, osize);
  3201.                             break;
  3202.                         }
  3203.                         else
  3204.                         {/* move a value temp to a value temp, effective nop */
  3205.                             return iv->cod_usedtail;
  3206.                         }
  3207.                     }
  3208.                     else if(datype & (A_AUTO|A_PARAM))
  3209.                     {
  3210.                         if(latype & A_MEMADDR)
  3211.                         {
  3212.                         unsigned char xsize = get_datasize(0, l);
  3213.                         int qc = 1;
  3214.                             if(        osize == BX
  3215.                                 ||    (osize == B8 && ddtype < D_FLOAT))
  3216.                                 obuf[qc++] = XTD;
  3217.                             obuf[qc++] = IMMED;
  3218.                             obuf[qc] = DEREF|xsize;
  3219.                             write_obuf(iv, obuf+1, qc);
  3220.                         }
  3221.                         obuf[oc] = SS|osize;
  3222.                         xtra += load_addr(iv, &obuf[oc], &obuf[oc+1], d, 2);
  3223.                         --iv->stackdepth;
  3224.                     }
  3225.                     else if(datype & A_DATA)
  3226.                     {
  3227.                         if(latype & A_MEMADDR)
  3228.                         {
  3229.                         unsigned char xsize = get_datasize(0, l);
  3230.                         int qc = 1;
  3231.                             if(        osize == BX
  3232.                                 ||    (osize == B8 && ddtype < D_FLOAT))
  3233.                                 obuf[qc++] = XTD;
  3234.                             obuf[qc++] = IMMED;
  3235.                             obuf[qc] = DEREF|xsize;
  3236.                             write_obuf(iv, obuf+1, qc);
  3237.                         }
  3238.                         obuf[oc] = SM|osize;
  3239.                         xtra += load_addr(iv, &obuf[oc], &obuf[oc+1], d, 2);
  3240.                         --iv->stackdepth;
  3241.                     }
  3242.                     else
  3243.                     {
  3244.                         return iv->cod_usedtail;
  3245.                     }
  3246.                 }
  3247.                 else if(latype & (A_AUTO|A_PARAM))
  3248.                 {
  3249.                 int lx;
  3250.                     if((latype & (A_POINTER|A_VALUE)) == (A_POINTER|A_VALUE))
  3251.                     {/* Put address on eval stack */
  3252.                         addr_toevalstack(iv, l);
  3253.                         if(opcode == assignop)
  3254.                           from_evalstack(iv, d, l);
  3255.                         break;
  3256.                     }
  3257.                     if(datype & (A_TEMP|A_RET))
  3258.                     {
  3259.                         if(opcode == derefop)
  3260.                             osize = B4;
  3261.                         obuf[oc] = LS|osize;
  3262.                         xtra += load_addr(iv, &obuf[oc], &obuf[oc+1], l, 2);
  3263.                         ++iv->stackdepth;
  3264.                         if(opcode == assignop)
  3265.                         {
  3266.                             /* Here we need a 'store from stack addr' inst */
  3267.                             if(datype & A_MEMADDR)
  3268.                             {/* Address was on the eval stack */
  3269.                                 write_obuf(iv, obuf, 1+xtra);
  3270.                                 mov_esdata(iv, 0, osize);
  3271.                                 break;
  3272.                             }
  3273.                         }
  3274.                     }
  3275.                     else if(datype & (A_AUTO|A_PARAM))
  3276.                     {
  3277.                         obuf[oc] = MOVSS|osize;
  3278.                         obuf[++oc] = 0;
  3279.                         lx = load_addr(iv, &obuf[oc], &obuf[oc+1], l, 2);
  3280.                         lx += load_addr(iv, &obuf[oc], &obuf[oc+1+lx], d, 0);
  3281.                         xtra += lx+1;
  3282.                     }
  3283.                     else if(datype & A_DATA)
  3284.                     {
  3285.                         obuf[oc] = MOVSM|osize;
  3286.                         obuf[++oc] = 0;
  3287.                         lx = load_addr(iv, &obuf[oc], &obuf[oc+1], l, 2);
  3288.                         lx += load_addr(iv, &obuf[oc], &obuf[oc+1+lx], d, 0);
  3289.                         xtra += lx+1;
  3290.                     }
  3291.                     else
  3292.                     {
  3293.                         return iv->cod_usedtail;
  3294.                     }
  3295.                 }
  3296.                 else if(latype & A_DATA)
  3297.                 {
  3298.                 int lx;
  3299.                     if((latype & (A_POINTER|A_VALUE)) == (A_POINTER|A_VALUE))
  3300.                     {/* Put address on eval stack */
  3301.                         addr_toevalstack(iv, l);
  3302.                         if(opcode == assignop)
  3303.                           from_evalstack(iv, d, l);
  3304.                         break;
  3305.                     }
  3306.                     if(datype & (A_TEMP|A_RET))
  3307.                     {
  3308.                         if(opcode == derefop)
  3309.                             osize = B4;
  3310.                         obuf[oc] = LM|osize;
  3311.                         xtra += load_addr(iv, &obuf[oc], &obuf[oc+1], l, 2);
  3312.                         ++iv->stackdepth;
  3313.                         if(opcode == assignop)
  3314.                         {
  3315.                             /* Here we need a 'store from stack addr' inst */
  3316.                              if(datype & A_MEMADDR)
  3317.                             {/* Address was on the eval stack */
  3318.                                 write_obuf(iv, obuf, 1+xtra);
  3319.                                 mov_esdata(iv, 0, osize);
  3320.                                 break;
  3321.                             }
  3322.                         }
  3323.                     }
  3324.                     else if(datype & (A_AUTO|A_PARAM))
  3325.                     {
  3326.                         obuf[oc] = MOVMS|osize;
  3327.                         obuf[++oc] = 0;
  3328.                         lx = load_addr(iv, &obuf[oc], &obuf[oc+1], l, 2);
  3329.                         lx += load_addr(iv, &obuf[oc], &obuf[oc+1+lx], d, 0);
  3330.                         xtra += lx+1;
  3331.                     }
  3332.                     else if(datype & A_DATA)
  3333.                     {
  3334.                         obuf[oc] = MOVMM|osize;
  3335.                         obuf[++oc] = 0;
  3336.                         lx = load_addr(iv, &obuf[oc], &obuf[oc+1], l, 2);
  3337.                         lx += load_addr(iv, &obuf[oc], &obuf[oc+1+lx], d, 0);
  3338.                         xtra += lx+1;
  3339.                     }
  3340.                     else
  3341.                     {
  3342.                         return iv->cod_usedtail;
  3343.                     }
  3344.                 }
  3345.                 else
  3346.                 {
  3347.                     return iv->cod_usedtail;
  3348.                 }
  3349.                 write_obuf(iv, obuf, 1+xtra);
  3350.             }/* END: move data directly */
  3351.             if(opcode == assignop && iv->has_structret)
  3352.             {
  3353.                 obuf[0] = XTD;
  3354.                 obuf[1] = PRUNESTRUCT;
  3355.                 write_obuf(iv, obuf, 2);
  3356.                 iv->has_structret = 0;
  3357.             }
  3358.             break;
  3359.         }
  3360.         case plusop:
  3361.         case minusop:
  3362.         case mulop:
  3363.         case divop:
  3364.         case orop:
  3365.         case xorop:
  3366.         case andop:
  3367.         case eqop:
  3368.         case neqop:
  3369.         case ltop:
  3370.         case gtop:
  3371.         case leop:
  3372.         case geop:
  3373.         {/* BINOPS */
  3374.         unsigned char ddtype;
  3375.         unsigned char osize;
  3376.         unsigned short latype = l->atype;
  3377.         unsigned short ratype = r->atype;
  3378.         PND bestptr = 0;
  3379.  
  3380.             if(latype & A_IMMED || ratype & A_IMMED)
  3381.             {
  3382.               if(ratype & A_IMMED)
  3383.               {/* IMMEDIATE IS ON THE RIGHT */
  3384.               bestptr = l;
  3385.  
  3386.                 data_toevalstack(iv, l, d);
  3387.                 if(check_binop_conversion(r, l))
  3388.                     do_conversion(iv, r, l);
  3389.  
  3390.                 data_toevalstack(iv, r, d);
  3391.  
  3392.                 ddtype = bestptr->dtype;
  3393.                 osize = l->opsize;
  3394.  
  3395.                 if(osize == BX || (osize == B8 && ddtype != D_FLOAT))
  3396.                     obuf[oc++] = XTD;
  3397.                 obuf[oc++] = binops[opcode]|get_datasize(opcode, l);
  3398.                 --iv->stackdepth;
  3399.                 write_obuf(iv, obuf, oc);
  3400.               }
  3401.               else /* IMMEDIATE IS ON THE LEFT */
  3402.               {
  3403.                 bestptr = r;
  3404.                 if(ratype & (A_TEMP|A_RET))
  3405.                 {
  3406.                     data_toevalstack(iv, r, d);
  3407.                     if(check_binop_conversion(l, r))
  3408.                         do_conversion(iv, l, r);
  3409.                     data_toevalstack(iv, l, d);
  3410.  
  3411.                     ddtype = bestptr->dtype;
  3412.                     osize = r->opsize;
  3413.  
  3414.                     if(        opcode != plusop
  3415.                         &&    opcode != eqop
  3416.                         &&    opcode != neqop
  3417.                         &&    opcode != andop
  3418.                         &&    opcode != orop
  3419.                         &&    opcode != mulop
  3420.                         &&    opcode != xorop
  3421.                         )
  3422.                     {/* stack order relevant */
  3423.                         if(osize <= B4)
  3424.                             obuf[0] = SWAP4;
  3425.                         else
  3426.                             obuf[0] = SWAP;
  3427.                         write_obuf(iv, obuf, 1);
  3428.                     }
  3429.                 }
  3430.                 else
  3431.                 {
  3432.                     data_toevalstack(iv, l, d);
  3433.                     data_toevalstack(iv, r, d);
  3434.                     if(check_binop_conversion(l, r))
  3435.                         do_conversion(iv, l, r);
  3436.  
  3437.                     ddtype = r->dtype;
  3438.                     osize = r->opsize;
  3439.                 }
  3440.  
  3441.                 if(osize == BX || (osize == B8 && ddtype != D_FLOAT))
  3442.                     obuf[oc++] = XTD;
  3443.                 obuf[oc++] = binops[opcode]|get_datasize(opcode, l);
  3444.                 write_obuf(iv, obuf, oc);
  3445.                 --iv->stackdepth;
  3446.               }/* END: IMMEDIATE IS ON LEFT */
  3447.             }/* IMMEDIATES */
  3448.             else
  3449.             {/* NOT IMMEDIATES */
  3450.  
  3451.                 if(ratype & (A_TEMP|A_RET))
  3452.                 {/* RIGHT HAND SIDE IS ALREADY ON STACK */
  3453.  
  3454.                     data_toevalstack(iv, r, d);
  3455.  
  3456.                     if(latype & (A_TEMP|A_RET))
  3457.                     {/* LEFT HAND SIDE WAS ALSO ON STACK */
  3458.  
  3459.                         /* Is it the same data as right hand side ?? */
  3460.                         if(l->TMPNUM == r->TMPNUM) 
  3461.                         {
  3462.                             if(r->opsize <= B4)
  3463.                                 obuf[0] = DUP4;
  3464.                             else
  3465.                                 obuf[0] = DUP;
  3466.                             write_obuf(iv, obuf, 1);
  3467.                             ++iv->stackdepth;
  3468.                             l->atype = r->atype;
  3469.                         }
  3470.                         else
  3471.                         {
  3472.                         unsigned char lltype = l->dtype;
  3473.                         unsigned lsize = l->opsize;
  3474.                             if(latype & A_MEMADDR)
  3475.                             {
  3476.                             unsigned char xsize = get_datasize(0, l);
  3477.                             int qc = 0;
  3478.  
  3479.                                 if(        (l->TMPNUM == d->TMPNUM)
  3480.                                     &&    ((d->atype & (A_ABSOLUTE|A_MEMADDR))
  3481.                                             == (A_ABSOLUTE|A_MEMADDR))
  3482.                                     )
  3483.                                 {/* it must expand with a DEREF1 */
  3484.                                     if(lsize <= B4)
  3485.                                         obuf[0] = DUP4;
  3486.                                     else
  3487.                                         obuf[0] = DUP;
  3488.                                     obuf[1] = DUMP;
  3489.                                     obuf[2] = DUMP;
  3490.                                     write_obuf(iv, obuf, 3);
  3491.  
  3492.                                     if(        lsize == BX
  3493.                                         ||    (lsize == B8 && lltype < D_FLOAT))
  3494.                                         obuf[qc++] = XTD;
  3495.                                     obuf[qc++] = IMMED;
  3496.                                     obuf[qc++] = DEREF1|xsize;
  3497.                                     write_obuf(iv, obuf, qc);
  3498.                                     ++iv->stackdepth;
  3499.                                 }
  3500.                                 else
  3501.                                 {
  3502.                                     obuf[0] = DUMP;
  3503.                                     write_obuf(iv, obuf, 1);
  3504.  
  3505.                                     if(        lsize == BX
  3506.                                         ||    (lsize == B8 && lltype < D_FLOAT))
  3507.                                         obuf[qc++] = XTD;
  3508.                                     obuf[qc++] = IMMED;
  3509.                                     obuf[qc++] = DEREF|xsize;
  3510.                                     write_obuf(iv, obuf, qc);
  3511.                                 }
  3512.                                 l->atype &= ~A_MEMADDR;
  3513.                                 l->atype |= A_VALUE;
  3514.  
  3515.                                 if(check_binop_conversion(r, l))
  3516.                                 {
  3517.                                     bestptr = r;
  3518.                                     do_conversion(iv, r, l);
  3519.                                 }
  3520.                                 obuf[0] = REGAIN;
  3521.                                 write_obuf(iv, obuf, 1);
  3522.  
  3523.                                 if(!bestptr)
  3524.                                  if(check_binop_conversion(l, r))
  3525.                                  {
  3526.                                     bestptr = l;
  3527.                                     do_conversion(iv, l, r);
  3528.                                  }
  3529.                             }
  3530.                         }
  3531.                     }
  3532.                     else
  3533.                     {/* LEFT HAND SIDE IS NOT ON STACK */
  3534.  
  3535.                         if(check_binop_conversion(l, r))
  3536.                         {
  3537.                             bestptr = l;
  3538.                             do_conversion(iv, l, r);
  3539.                         }
  3540.                         data_toevalstack(iv, l, d);
  3541.                         if(!bestptr)
  3542.                          if(check_binop_conversion(r, l))
  3543.                          {
  3544.                             bestptr = r;
  3545.                             do_conversion(iv, r, l);
  3546.                          }
  3547.                         if(        opcode != plusop
  3548.                             &&    opcode != eqop
  3549.                             &&    opcode != neqop
  3550.                             &&    opcode != andop
  3551.                             &&    opcode != orop
  3552.                             &&  opcode != mulop
  3553.                             &&    opcode != xorop
  3554.                             )
  3555.                         {/* stack order relevant */
  3556.                             if(r->opsize <= B4)
  3557.                                 obuf[0] = SWAP4;
  3558.                             else
  3559.                                 obuf[0] = SWAP;
  3560.                             write_obuf(iv, obuf, 1);
  3561.                         }
  3562.                     }
  3563.                 }
  3564.                 else /* ONLY LEFT HAND SIDE CAN BE ON STACK */
  3565.                 {
  3566.                     data_toevalstack(iv, l, d);
  3567.                     if(check_binop_conversion(r, l))
  3568.                     {
  3569.                         bestptr = r;
  3570.                         do_conversion(iv, r, l);
  3571.                     }
  3572.  
  3573.                     data_toevalstack(iv, r, d);
  3574.                     if(!bestptr)
  3575.                      if(check_binop_conversion(l, r))
  3576.                      {
  3577.                         bestptr = l;
  3578.                         do_conversion(iv, l, r);
  3579.                     }
  3580.                 }
  3581.                 if(!bestptr)
  3582.                     bestptr = l;
  3583.  
  3584.                 ddtype = bestptr->dtype;
  3585.                 osize = bestptr->opsize;
  3586.  
  3587.                 if(osize == BX || (osize==B8 && ddtype != D_FLOAT))
  3588.                     obuf[oc++] = XTD;
  3589.                 obuf[oc++] = binops[opcode]|get_datasize(opcode, bestptr);
  3590.                 write_obuf(iv, obuf, oc);
  3591.                 --iv->stackdepth;
  3592.             }/* END: NOT IMMEDIATES */
  3593.  
  3594.             if(opcode >= eqop)
  3595.             {
  3596.                 bestptr = &longtype;
  3597.             }
  3598.  
  3599.             if(check_assignment_conversion(d, bestptr))
  3600.                 do_conversion(iv, d, bestptr);
  3601.             bestptr->atype &= ~A_MEMADDR;
  3602.             bestptr->atype |= A_VALUE;
  3603.             from_evalstack(iv, d, bestptr);
  3604.  
  3605.             break;
  3606.         }/* END: BINOPS */
  3607.  
  3608.         case lshop:
  3609.         case rshop:
  3610.         {/* SHIFTS */
  3611.         unsigned short latype = l->atype;
  3612.         unsigned short ratype = r->atype;
  3613.         PND bestptr;
  3614.  
  3615.  
  3616.             if(latype & A_IMMED || ratype & A_IMMED)
  3617.             {
  3618.               if(ratype & A_IMMED)
  3619.               {/* IMMEDIATE IS ON THE RIGHT */
  3620.                 data_toevalstack(iv, l, d);
  3621.  
  3622.                 obuf[0] = XTD;
  3623.                 if(opcode == lshop)
  3624.                 {
  3625.                     obuf[1] = LSHI|get_datasize(opcode, l);
  3626.                     obuf[2] = r->data->Uuchar;
  3627.                 }
  3628.                 else if(opcode == rshop)
  3629.                 {
  3630.                     obuf[1] = RSHI|get_datasize(opcode, l);
  3631.                     obuf[2] = r->data->Uuchar;
  3632.                 }
  3633.                 write_obuf(iv, obuf, 3);
  3634.               }
  3635.               else /* IMMEDIATE IS ON THE LEFT */
  3636.               {
  3637.                 if(ratype & (A_TEMP|A_RET))
  3638.                 {
  3639.                     data_toevalstack(iv, r, d);
  3640.                     data_toevalstack(iv, l, d);
  3641.                     if(r->opsize <= B4)
  3642.                         obuf[0] = SWAP4;
  3643.                     else
  3644.                         obuf[0] = SWAP;
  3645.                     write_obuf(iv, obuf, 1);
  3646.                 }
  3647.                 else
  3648.                 {
  3649.                     data_toevalstack(iv, l, d);
  3650.                     data_toevalstack(iv, r, d);
  3651.                 }
  3652.  
  3653.                 obuf[0] = XTD;
  3654.                 obuf[1] = binops[opcode]|get_datasize(opcode, l);
  3655.                 write_obuf(iv, obuf, 2);
  3656.                 --iv->stackdepth;
  3657.               }
  3658.             }
  3659.             else
  3660.             {/* NOT IMMEDIATES */
  3661.  
  3662.                 if(ratype & (A_TEMP|A_RET))
  3663.                 {/* RIGHT HAND SIDE IS ALREADY ON STACK */
  3664.  
  3665.                     data_toevalstack(iv, r, d);
  3666.  
  3667.                     if(latype & (A_TEMP|A_RET))
  3668.                     {/* LEFT HAND SIDE WAS ALSO ON STACK */
  3669.  
  3670.                         /* Is it the same data as right hand side ?? */
  3671.                         if(l->TMPNUM == r->TMPNUM)
  3672.                         {
  3673.                             if(l->opsize <= B4 && r->opsize <= B4)
  3674.                                 obuf[0] = DUP4;
  3675.                             else
  3676.                                 obuf[0] = DUP;
  3677.                             write_obuf(iv, obuf, 1);
  3678.                             ++iv->stackdepth;
  3679.                             l->atype = r->atype;
  3680.                         }
  3681.                         else
  3682.                         {/* reversed stack and not same data */
  3683.  
  3684.                             if(latype & A_MEMADDR)
  3685.                             {
  3686.                             unsigned char xsize = l->opsize;
  3687.                             int qc = 0;
  3688.  
  3689.                                 if(        (l->TMPNUM == d->TMPNUM)
  3690.                                     &&    ((d->atype & (A_ABSOLUTE|A_MEMADDR))
  3691.                                             == (A_ABSOLUTE|A_MEMADDR))
  3692.                                     )
  3693.                                 {/* it must expand with a DEREF1 */
  3694.                                     if(l->opsize <= B4)
  3695.                                         obuf[0] = DUP4;
  3696.                                     else
  3697.                                         obuf[0] = DUP;
  3698.                                     obuf[1] = DUMP;
  3699.                                     obuf[2] = DUMP;
  3700.                                     write_obuf(iv, obuf, 3);
  3701.  
  3702.                                     if(l->opsize == B8)
  3703.                                         obuf[qc++] = XTD;
  3704.                                     obuf[qc++] = IMMED;
  3705.                                     obuf[qc++] = DEREF1|xsize;
  3706.                                     write_obuf(iv, obuf, qc);
  3707.                                     ++iv->stackdepth;
  3708.                                 }
  3709.                                 else
  3710.                                 {
  3711.                                     obuf[0] = DUMP;
  3712.                                     write_obuf(iv, obuf, 1);
  3713.  
  3714.                                     if(l->opsize == B8)
  3715.                                         obuf[qc++] = XTD;
  3716.                                     obuf[qc++] = IMMED;
  3717.                                     obuf[qc++] = DEREF|xsize;
  3718.                                     write_obuf(iv, obuf, qc);
  3719.                                 }
  3720.                                 l->atype &= ~A_MEMADDR;
  3721.                                 l->atype |= A_VALUE;
  3722.  
  3723.                                 obuf[0] = REGAIN;
  3724.                                 write_obuf(iv, obuf, 1);
  3725.                             }
  3726.                         }
  3727.                     }
  3728.                     else
  3729.                     {/* LEFT HAND SIDE IS NOT ON STACK */
  3730.  
  3731.                         data_toevalstack(iv, l, d);
  3732.                         if(r->opsize <= B4 && l->opsize <= B4)
  3733.                             obuf[0] = SWAP4;
  3734.                         else
  3735.                             obuf[0] = SWAP;
  3736.                         write_obuf(iv, obuf, 1);
  3737.                     }
  3738.                 }
  3739.                 else /* ONLY LEFT HAND SIDE CAN BE ON STACK */
  3740.                 {
  3741.                     data_toevalstack(iv, l, d);
  3742.                     data_toevalstack(iv, r, d);
  3743.                 }
  3744.  
  3745.                 /* ENSURE THAT THE RIGHT SIDE IS A LONG OR A LONG LONG */
  3746.                 bestptr = (l->size > 4) ? &longlongtype : &longtype;
  3747.                 if(check_assignment_conversion(bestptr, r))
  3748.                     do_conversion(iv, bestptr, r);
  3749.  
  3750.                 obuf[0] = XTD;
  3751.                 obuf[1] = binops[opcode]|get_datasize(opcode, l);
  3752.                 write_obuf(iv, obuf, 2);
  3753.                 --iv->stackdepth;
  3754.             }/* END: NOT IMMEDIATES */
  3755.  
  3756.             if(check_assignment_conversion(d, l))
  3757.                 do_conversion(iv, d, l);
  3758.             l->atype &= ~A_MEMADDR;
  3759.             l->atype |= A_VALUE;
  3760.             from_evalstack(iv, d, l);
  3761.  
  3762.             break;
  3763.         }/* END: SHIFTS */
  3764.         case modop:
  3765.         {/* MODULUS */
  3766.         unsigned short latype = l->atype;
  3767.         unsigned short ratype = r->atype;
  3768.         PND bestptr;
  3769.  
  3770.             if(latype & A_IMMED || ratype & A_IMMED)
  3771.             {
  3772.               if(ratype & A_IMMED)
  3773.               {/* IMMEDIATE IS ON THE RIGHT */
  3774.                 data_toevalstack(iv, l, d);
  3775.  
  3776.                 if(l->opsize == B8)
  3777.                 {
  3778.                     obuf[oc++] = XTD;
  3779.                 }
  3780.                 if(d->size == 2)
  3781.                 {
  3782.                     obuf[oc++] = IMMED;
  3783.                     obuf[oc++] = MODI|get_datasize(opcode, l);
  3784.                     *((short*)&obuf[oc]) = r->data->Uushort;
  3785.                     xtra = 2;
  3786.                 }
  3787.                 else
  3788.                 {/* no fast instructions available */
  3789.                     data_toevalstack(iv, r, d);
  3790.                     obuf[oc++] = binops[opcode]|get_datasize(opcode, l);
  3791.                     --iv->stackdepth;
  3792.                 }
  3793.                 write_obuf(iv, obuf, oc+xtra);
  3794.               }
  3795.               else /* IMMEDIATE IS ON THE LEFT */
  3796.               {
  3797.  
  3798.                 if(ratype & (A_TEMP|A_RET))
  3799.                 {
  3800.                     data_toevalstack(iv, r, d);
  3801.                     data_toevalstack(iv, l, d);
  3802.                     if(r->opsize <= B4)
  3803.                         obuf[0] = SWAP4;
  3804.                     else
  3805.                         obuf[0] = SWAP;
  3806.                     write_obuf(iv, obuf, 1);
  3807.                 }
  3808.                 else
  3809.                 {/* load eval stack without regard for conversion */
  3810.                     data_toevalstack(iv, l, d);
  3811.                     data_toevalstack(iv, r, d);
  3812.                 }
  3813.  
  3814.                 if(r->opsize == B8)
  3815.                 {
  3816.                     obuf[oc++] = XTD;
  3817.                 }
  3818.                 obuf[oc++] = binops[opcode]|get_datasize(opcode, l);
  3819.                 write_obuf(iv, obuf, oc);
  3820.                 --iv->stackdepth;
  3821.               }
  3822.             }
  3823.             else
  3824.             {/* NOT IMMEDIATES */
  3825.                 if(ratype & (A_TEMP|A_RET))
  3826.                 {/* RIGHT HAND SIDE IS ALREADY ON STACK */
  3827.  
  3828.                     data_toevalstack(iv, r, d);
  3829.  
  3830.                     if(latype & (A_TEMP|A_RET))
  3831.                     {/* LEFT HAND SIDE WAS ALSO ON STACK */
  3832.  
  3833.                         /* Is it the same data as right hand side ?? */
  3834.                         if(l->TMPNUM == r->TMPNUM)
  3835.                         {
  3836.                             if(l->opsize <= B4 && r->opsize <= B4)
  3837.                                 obuf[0] = DUP4;
  3838.                             else
  3839.                                 obuf[0] = DUP;
  3840.                             write_obuf(iv, obuf, 1);
  3841.                             ++iv->stackdepth;
  3842.                             l->atype = r->atype;
  3843.                         }
  3844.                         else
  3845.                         {/* reversed stack and not same data */
  3846.  
  3847.                             if(latype & A_MEMADDR)
  3848.                             {
  3849.                             unsigned char xsize = get_datasize(0, l);
  3850.                             int qc = 0;
  3851.  
  3852.                                 if(        (l->TMPNUM == d->TMPNUM)    
  3853.                                     &&    ((d->atype & (A_ABSOLUTE|A_MEMADDR))
  3854.                                             == (A_ABSOLUTE|A_MEMADDR))
  3855.                                     )
  3856.                                 {/* it must expand with a DEREF1 */
  3857.                                     if(r->opsize <= B4)
  3858.                                         obuf[0] = DUP4;
  3859.                                     else
  3860.                                         obuf[0] = DUP;
  3861.                                     obuf[1] = DUMP;
  3862.                                     obuf[2] = DUMP;
  3863.                                     write_obuf(iv, obuf, 3);
  3864.  
  3865.                                     if(r->opsize == B8)
  3866.                                         obuf[qc++] = XTD;
  3867.                                     obuf[qc++] = IMMED;
  3868.                                     obuf[qc++] = DEREF1|xsize;
  3869.                                     write_obuf(iv, obuf, qc);
  3870.                                     ++iv->stackdepth;
  3871.                                 }
  3872.                                 else
  3873.                                 {
  3874.                                     obuf[0] = DUMP;
  3875.                                     write_obuf(iv, obuf, 1);
  3876.  
  3877.                                     if(r->opsize == B8)
  3878.                                         obuf[qc++] = XTD;
  3879.                                     obuf[qc++] = IMMED;
  3880.                                     obuf[qc++] = DEREF|xsize;
  3881.                                     write_obuf(iv, obuf, qc);
  3882.                                 }
  3883.                                 l->atype &= ~A_MEMADDR;
  3884.                                 l->atype |= A_VALUE;
  3885.  
  3886.                                 obuf[0] = REGAIN;
  3887.                                 write_obuf(iv, obuf, 1);
  3888.                             }
  3889.                         }
  3890.                     }
  3891.                     else
  3892.                     {/* LEFT HAND SIDE IS NOT ON STACK */
  3893.  
  3894.                         data_toevalstack(iv, l, d);
  3895.                         if(r->opsize <= B4 && l->opsize <= B4)
  3896.                             obuf[0] = SWAP4;
  3897.                         else
  3898.                             obuf[0] = SWAP;
  3899.                         write_obuf(iv, obuf, 1);
  3900.                     }
  3901.                 }
  3902.                 else /* ONLY LEFT HAND SIDE CAN BE ON STACK */
  3903.                 {
  3904.                     data_toevalstack(iv, l, d);
  3905.                     data_toevalstack(iv, l, d);
  3906.                 }
  3907.  
  3908.                 /* ENSURE THAT THE RIGHT SIDE IS A LONG OR A LONG LONG */
  3909.                 bestptr = (l->size > 4) ? &longlongtype : &longtype;
  3910.                 if(check_assignment_conversion(bestptr, r))
  3911.                     do_conversion(iv, bestptr, r);
  3912.  
  3913.                 if(l->opsize == B8)
  3914.                 {
  3915.                     obuf[oc++] = XTD;
  3916.                 }
  3917.                 obuf[oc++] = binops[opcode]|get_datasize(opcode, l);
  3918.                 write_obuf(iv, obuf, oc);
  3919.                 --iv->stackdepth;
  3920.             }/* END: NOT IMMEDIATES */
  3921.  
  3922.             if(check_assignment_conversion(d, l))
  3923.                 do_conversion(iv, d, l);
  3924.             l->atype &= ~A_MEMADDR;
  3925.             l->atype |= A_VALUE;
  3926.             from_evalstack(iv, d, l);
  3927.  
  3928.             break;
  3929.         }/* END: MODULUS */
  3930.         case truthop:
  3931.         case aliastmpop:
  3932.         {/* no immediates */
  3933.  
  3934.             data_toevalstack(iv, l, d);
  3935.  
  3936.             if(l->opsize != B1)
  3937.             {/* no need to get truth of byte sized elements */
  3938.                 if(l->opsize == BX)
  3939.                 {
  3940.                     obuf[oc++] = XTD;
  3941.                 }
  3942.                 obuf[oc++] = TRUTHOF|l->opsize;
  3943.                 write_obuf(iv, obuf, oc);
  3944.             }
  3945.             break;
  3946.         }
  3947.         case complop:
  3948.         case notop:
  3949.         {/* no immediates */
  3950.         unsigned char osize = get_datasize(opcode, l);
  3951.  
  3952.             data_toevalstack(iv, l, d);
  3953.             if(osize == BX)
  3954.             {/* only notop can operate on long double */
  3955.                 obuf[oc++] = XTD;
  3956.             }
  3957.             obuf[oc++] = binops[opcode]|osize;
  3958.             write_obuf(iv, obuf, oc);
  3959.             break;
  3960.         }
  3961.         case negop:
  3962.         {/* no immediates */
  3963.  
  3964.             data_toevalstack(iv, l, d);
  3965.             if(l->opsize == BX || (l->opsize==B8 && l->dtype != D_FLOAT))
  3966.             {
  3967.                 obuf[oc++] = XTD;
  3968.             }
  3969.             obuf[oc++] = binops[opcode]|get_datasize(opcode, l);
  3970.             write_obuf(iv, obuf, oc);
  3971.             break;
  3972.         }
  3973.         case copyop:
  3974.         {
  3975.             if(d->atype & (A_TEMP|A_RET))
  3976.             {
  3977.                 if(!(l->atype & (A_TEMP|A_RET)))
  3978.                 {
  3979.                     data_toevalstack(iv, l, d);
  3980.                 }
  3981.             }
  3982.             else
  3983.             {
  3984.                 if(!(l->atype & (A_TEMP|A_RET)))
  3985.                 {
  3986.                     data_toevalstack(iv, d, d);
  3987.                     data_toevalstack(iv, l, d);
  3988.                 }
  3989.                 else
  3990.                 {
  3991.                     data_toevalstack(iv, d, d);
  3992.                     obuf[0] = SWAP4;
  3993.                     write_obuf(iv, obuf, 1);
  3994.                 }
  3995.             }
  3996.             load_val(iv, d->size);
  3997.             obuf[0] = MOVAAC;
  3998.             write_obuf(iv, obuf, 1);
  3999.             iv->stackdepth -= 3;
  4000.             break;
  4001.         }
  4002.         case castop:
  4003.         {
  4004.             data_toevalstack(iv, l, d);
  4005.             if(check_assignment_conversion(d, l))
  4006.                 do_conversion(iv, d, l);
  4007.             break;
  4008.         }
  4009.         case jmploopop:
  4010.         case jmpcontinueop:
  4011.         case jmpbreakop:
  4012.         case jmpgotoop:
  4013.         case ljmptrueop:
  4014.         case jmptrueop:
  4015.         case ljmpfalseop:
  4016.         case jmpfalseop:
  4017.         case funcstartop:
  4018.         case funcstopop:
  4019.         {/* start with max sized jmps, they will be shortened later */
  4020.         void *fixjmp;
  4021.             if(opcode == jmptrueop)
  4022.             {
  4023.                 obuf[0] = JMPT|J4;
  4024.                 --iv->stackdepth;
  4025.             }
  4026.             else if(opcode == ljmptrueop)
  4027.             {
  4028.                 obuf[0] = LJMPT|J4;
  4029.             }
  4030.             else if(opcode == jmpfalseop)
  4031.             {
  4032.                 obuf[0] = JMPF|J4;
  4033.                 --iv->stackdepth;
  4034.             }
  4035.             else if(opcode == ljmpfalseop)
  4036.             {
  4037.                 obuf[0] = LJMPF|J4;
  4038.             }
  4039.             else if(opcode == funcstartop || opcode == funcstopop)
  4040.             {
  4041.                 obuf[0] = LOCATE|J4;
  4042.             }
  4043.             else
  4044.                 obuf[0] = JMP|J4;
  4045.             fixjmp = write_obuf(iv, obuf, 5);
  4046.             addto_jmplist(iv, p, fixjmp);
  4047.             break;
  4048.         }
  4049.         case clrdatop:
  4050.         {
  4051.             addr_toevalstack(iv, d);
  4052.             data_toevalstack(iv, l, 0);
  4053.             obuf[0] = XTD;
  4054.             obuf[1] = CLRDAT;
  4055.             write_obuf(iv, obuf, 2);
  4056.             iv->stackdepth -= 2;
  4057.             break;
  4058.         }
  4059.         case getbitfieldop:
  4060.         {
  4061.             data_toevalstack(iv, r, d);
  4062.             obuf[0] = XTD;
  4063.             obuf[1] = GETBITFIELD;
  4064.             obuf[2] = l->data->uchr.d[0];    /* shift */
  4065.             obuf[3] = l->data->uchr.d[1];    /* size */
  4066.             obuf[4] = l->data->uchr.d[2];    /* sign */
  4067.             write_obuf(iv, obuf, 5);
  4068.             break;
  4069.         }
  4070.         case putbitfieldop:
  4071.         {
  4072.             if(!(d->atype & (A_TEMP|A_RET)))
  4073.             {/* destination address to stack */
  4074.                 addr_toevalstack(iv, d);
  4075.  
  4076.                 if(!(r->atype & (A_TEMP|A_RET)))
  4077.                 {
  4078.                     data_toevalstack(iv, r, d);
  4079.                 }
  4080.                 else
  4081.                 {/* data was on stack */
  4082.                     obuf[0] = SWAP;
  4083.                     write_obuf(iv, obuf, 1);
  4084.                 }
  4085.             }
  4086.             else
  4087.             {/* destination address is on stack */
  4088.                 data_toevalstack(iv, r, d);
  4089.             }
  4090.             if(check_assignment_conversion(d, r))
  4091.                 do_conversion(iv, d, r);
  4092.  
  4093.             obuf[0] = XTD;
  4094.             obuf[1] = PUTBITFIELD;
  4095.             obuf[2] = l->data->uchr.d[0];    /* shift */
  4096.             obuf[3] = l->data->uchr.d[1];    /* size */
  4097.             obuf[4] = d->size;
  4098.             write_obuf(iv, obuf, 5);
  4099.             iv->stackdepth -= 2;
  4100.             break;
  4101.         }
  4102.         case retstructop:
  4103.         {
  4104.             addr_toevalstack(iv, d);
  4105.             obuf[0] = XTD;
  4106.             obuf[1] = RETSTRUCT;
  4107.             *((unsigned short*)&obuf[2]) = l->data->ulng.d[0] >>2;    /* size */
  4108.             *((unsigned short*)&obuf[4]) = l->data->ulng.d[1] >>2;    /* offset */
  4109.             write_obuf(iv, obuf, 6);
  4110.             break;
  4111.         }
  4112.         case retdataop:
  4113.         case retvoidop:
  4114.         {
  4115.             obuf[0] = RET;
  4116.             write_obuf(iv, obuf, 1);
  4117.             break;
  4118.         }
  4119.         case callfuncop:
  4120.         {
  4121.             obuf[0] = XTD;
  4122.             obuf[1] = CALLSETUP;
  4123.             *((long*)&obuf[2]) = l->data->ulng.d[0];    /* argsize */
  4124.             write_obuf(iv, obuf, 6);
  4125.             break;
  4126.         }
  4127.         case switchop:
  4128.         {
  4129.         void *fixjmp;
  4130.             obuf[0] = XTD;
  4131.             obuf[1] = SWITCH;
  4132.             *((short*)(&obuf[2])) = d->data->ulng.d[1];    /* swnode */
  4133.             write_obuf(iv, obuf, 4);
  4134.  
  4135.             /* Default jmp */
  4136.             obuf[0] = JMP|D4;
  4137.             fixjmp = write_obuf(iv, obuf, 5);
  4138.             addto_jmplist(iv, p, fixjmp);
  4139.             --iv->stackdepth;
  4140.             break;
  4141.         }
  4142.         case compsavop:
  4143.         case totmpop:
  4144.         {
  4145.             data_toevalstack(iv, l, d);
  4146.             break;
  4147.         }
  4148.         case argop:
  4149.         {
  4150.         unsigned char op =    arg_toevalstack(iv, l, d->ARGSIZE);
  4151.             if(!(iv->in_builtin))
  4152.             {
  4153.                 load_val(iv, d->ARGOFS);
  4154.                 load_val(iv, d->ARGSIZE);
  4155.                 obuf[0] = op;
  4156.                 write_obuf(iv, obuf, 1);
  4157.                 iv->stackdepth -= 3;
  4158.             }
  4159.             break;
  4160.         }
  4161.         default:
  4162.         {
  4163. #if 0
  4164.             obuf[0] = NOP;
  4165.             write_obuf(iv, obuf, 1);
  4166. #endif
  4167.             break;
  4168.         }
  4169.     }/* END: switch(opcode) */
  4170.     if(iv->stackdepth > iv->maxdepth)
  4171.         iv->maxdepth = iv->stackdepth;
  4172.     if(iv->stackdepth < iv->mindepth)
  4173.         iv->mindepth = iv->stackdepth;
  4174.  
  4175.     return iv->cod_usedtail;
  4176. }/* END: gen_inst() */
  4177.  
  4178. static void
  4179. set_op(PND pnd, PopA ptr, unsigned char otype)
  4180. {
  4181. unsigned char optype  = otype & 0xe0;
  4182. unsigned char isize = otype & 0x1f;
  4183.  
  4184.     pnd->data = (DATUM *)ptr;
  4185.     if(optype <= OPIMMED4)
  4186.     {
  4187.         pnd->dtype = optype >> 5;
  4188.         pnd->quals = Q_CONST;
  4189.         pnd->size = isize;
  4190.         pnd->opsize = get_size(pnd->dtype, isize);
  4191.         pnd->atype = A_IMMED;
  4192.     } /* END: OPIMMED */
  4193.     else
  4194.     {
  4195.     unsigned short type = GS(ptr->dtype);
  4196.         pnd->dtype = type & 0xff;
  4197.         pnd->quals = (type >> 8) & 0xff;
  4198.         pnd->size = GL(ptr->dsize);
  4199.         pnd->opsize = get_size(pnd->dtype, pnd->size);
  4200.         pnd->atype = GS(ptr->atype);
  4201.  
  4202.         if(optype == OPAUTO)
  4203.         {
  4204.             if(GL(ptr->pofs) >= 0)
  4205.             {
  4206.                 pnd->atype &= ~A_AUTO;
  4207.                 pnd->atype |= A_PARAM;
  4208.             }
  4209.         }
  4210.     }
  4211. }/* END: set_op() */
  4212. static void *
  4213. decode_anf(Piv iv, unsigned char *p)
  4214. {
  4215. void *dptr;
  4216. void *lptr;
  4217. void *rptr;
  4218.  
  4219.     if(iv->debug >= '4')
  4220.         cfeprintf("DECODE inst(%u) `%s'\n", *p, oxgenops[*p]);
  4221.  
  4222.     if(*p == 0)
  4223.         return POP->next;
  4224.  
  4225.  
  4226.     iv->ob->p = p;
  4227.     switch(*p)
  4228.     {
  4229.         case regainop:
  4230.         case grabop:
  4231.         case retvoidop:
  4232.         {/* 0 address mode */
  4233.             break;
  4234.         }
  4235.         case jmploopop:
  4236.         case jmpcontinueop:
  4237.         case jmpbreakop:
  4238.         case jmpgotoop:
  4239.         case ljmptrueop:
  4240.         case jmptrueop:
  4241.         case ljmpfalseop:
  4242.         case jmpfalseop:
  4243.         case funcstartop:
  4244.         case funcstopop:
  4245.         case retdataop:
  4246.         {/* 1 address mode */
  4247.             dptr = (p+8);
  4248.             set_op(&iv->ob->d, dptr, p[1]);
  4249.             break;
  4250.         }
  4251.         case getvalop:
  4252.         case derefop:
  4253.         case assignop:
  4254.         case duptmpop:
  4255.         case truthop:
  4256.         case aliastmpop:
  4257.         case negop:
  4258.         case complop:
  4259.         case notop:
  4260.         case copyop:
  4261.         case castop:
  4262.         case clrdatop:
  4263.         case compsavop:
  4264.         case totmpop:
  4265.         case retstructop:
  4266.         case switchop:
  4267.         case argop:
  4268.         {/* 2 address mode */
  4269.             dptr = (p+8);
  4270.             lptr = (((char*)dptr) + (p[1] & 0x1f));
  4271.             set_op(&iv->ob->d, dptr, p[1]);
  4272.             set_op(&iv->ob->l, lptr, p[2]);
  4273.             break;
  4274.         }
  4275.         case plusop:
  4276.         case minusop:
  4277.         case mulop:
  4278.         case divop:
  4279.         case modop:
  4280.         case orop:
  4281.         case xorop:
  4282.         case andop:
  4283.         case eqop:
  4284.         case neqop:
  4285.         case ltop:
  4286.         case gtop:
  4287.         case leop:
  4288.         case geop:
  4289.         case lshop:
  4290.         case rshop:
  4291.         case getbitfieldop:
  4292.         case callfuncop:
  4293.         case putbitfieldop:
  4294.         {/* 3 address mode */
  4295.             dptr = (p+8);
  4296.             lptr = (((char*)dptr) + (p[1] & 0x1f));
  4297.             rptr = (((char*)lptr) + (p[2] & 0x1f));
  4298.             set_op(&iv->ob->d, dptr, p[1]);
  4299.             set_op(&iv->ob->l, lptr, p[2]);
  4300.             set_op(&iv->ob->r, rptr, p[3]);
  4301.             break;
  4302.         }
  4303.         default:
  4304.         {
  4305.             return POP->next;
  4306.         }
  4307.     }/* END: switch(*p) */
  4308.  
  4309.     /* Save pointers to the machine instructions generated by this ANF code */
  4310.     iv->ob->startinst = iv->cod;
  4311.     iv->ob->endinst = gen_inst(iv, iv->ob);
  4312.  
  4313.     if(iv->cod != iv->ob->startinst)
  4314.     {/* instructions were generated */
  4315.         link_ob(iv);
  4316.     }
  4317.     return POP->next;
  4318. }/* END: decode_anf() */
  4319.  
  4320. static void *
  4321. skip_bracket(unsigned char *p)
  4322. {
  4323. long opcode = *p;
  4324. int opcount = 0;
  4325.  
  4326.     for(;;)
  4327.     {
  4328.         if(*p == opcode)
  4329.             ++opcount;
  4330.         else if(*p == endop && GL(POP->data) == opcode)
  4331.         {
  4332.             if(--opcount == 0) {
  4333.                 return p;
  4334.             }
  4335.         }
  4336.         else if(*p == endfileop || *p == endallop)
  4337.         {
  4338.             PERROR(pName ":ERROR: Malformed input file3=%u=%p",*p, p);
  4339.         }
  4340.         p = POP->next;
  4341.     }
  4342.     return 0;
  4343. }
  4344. static void *
  4345. do_strelem(Piv iv, unsigned char *p)
  4346. {
  4347. void *sp = p;
  4348. unsigned char *q = skip_bracket(p);
  4349. void *elem[20];    
  4350. void *elemq[20];
  4351. int elemcnt, i;
  4352.  
  4353.     elemcnt = 0;
  4354.     p = POP->next;
  4355.     while(p < q)
  4356.     {/* Pick up nested elements */
  4357.     unsigned char opcode = *p;
  4358.         if(opcode == strelemop || opcode == ptrelemop || opcode == arrayelemop)
  4359.         {
  4360.         void *qq = skip_bracket(p);
  4361.             elem[elemcnt] = p;
  4362.             elemq[elemcnt++] = qq;
  4363.             p = qq;
  4364.         }
  4365.         p = POP->next;
  4366.     }
  4367.  
  4368.     /* Dump the nested elements in the order encountered */
  4369.     for(i = 0; i < elemcnt; ++i)
  4370.     {
  4371.         do_something(iv, elem[i]);
  4372.     } 
  4373.  
  4374.     /* Dump the remainder of bracket */
  4375.     p = sp;
  4376.     elemcnt = 0;
  4377.     p = POP->next;
  4378.      while(p < q)
  4379.     {
  4380.     unsigned char opcode = *p;
  4381.         if(opcode == strelemop || opcode == ptrelemop || opcode == arrayelemop)
  4382.             p = ((Pop)elemq[elemcnt++])->next;
  4383.         else
  4384.             p = do_something(iv, p);
  4385.     }
  4386.     return ((Pop)q)->next;
  4387. }
  4388. static void *
  4389. do_ptrelem(Piv iv, unsigned char *p)
  4390. {
  4391. void *sp = p;
  4392. unsigned char *q = skip_bracket(p);
  4393. void *elem[20];    
  4394. void *elemq[20];
  4395. int elemcnt, i;
  4396.  
  4397.     elemcnt = 0;
  4398.     p = POP->next;
  4399.     while(p < q)
  4400.     {/* Pick up nested elements */
  4401.     unsigned char opcode = *p;
  4402.         if(opcode == arrayelemop || opcode == ptrelemop || opcode == strelemop)
  4403.         {
  4404.         void *qq = skip_bracket(p);
  4405.             elem[elemcnt] = p;
  4406.             elemq[elemcnt++] = qq;
  4407.             p = qq;
  4408.         }
  4409.         p = POP->next;
  4410.     }
  4411.  
  4412.     /* Dump the nested elements in the order encountered */
  4413.     for(i = 0; i < elemcnt; ++i)
  4414.     {
  4415.         do_something(iv, elem[i]);
  4416.     } 
  4417.  
  4418.     /* Dump the remainder of bracket */
  4419.     p = sp;
  4420.     elemcnt = 0;
  4421.     p = POP->next;
  4422.      while(p < q)
  4423.     {
  4424.     unsigned char opcode = *p;
  4425.         if(opcode == arrayelemop || opcode == strelemop || opcode == ptrelemop)
  4426.             p = ((Pop)elemq[elemcnt++])->next;
  4427.         else
  4428.             p = do_something(iv, p);
  4429.     }
  4430.     return ((Pop)q)->next;
  4431. }
  4432. static void *
  4433. do_arrayelem(Piv iv, unsigned char *p)
  4434. {/* Arrange output for the stack machine */
  4435. void *sp = p;
  4436. unsigned char *q = skip_bracket(p);
  4437. void *sadims[10];
  4438. void *sadimsq[10];
  4439. void *spdims[10];    
  4440. void *spdimsq[10];
  4441. void *elem[20];    
  4442. void *elemq[20];
  4443. int sacnt, spcnt, elemcnt, i;
  4444.  
  4445.     /* Scan over the bracket and pick up the dimension computations */
  4446.     elemcnt= sacnt = spcnt = 0;
  4447.     p = POP->next;
  4448.     while(p < q)
  4449.     {
  4450.     unsigned char opcode = *p;
  4451.         if(opcode == arraydimsop)
  4452.         {
  4453.         void *qq = skip_bracket(p);
  4454.             sadims[sacnt] = p;
  4455.             sadimsq[sacnt++] = qq;
  4456.             p = qq;
  4457.         }
  4458.         else if(opcode == ptrdimsop)
  4459.         {
  4460.         void *qq = skip_bracket(p);
  4461.             spdims[spcnt] = p;
  4462.             spdimsq[spcnt++] = qq;
  4463.             p = qq;
  4464.         }
  4465.         else if(opcode==arrayelemop || opcode==ptrelemop || opcode==strelemop)
  4466.         {
  4467.         void *qq = skip_bracket(p);
  4468.             elem[elemcnt] = p;
  4469.             elemq[elemcnt++] = qq;
  4470.             p = qq;
  4471.         }
  4472.         p = POP->next;
  4473.     }
  4474.  
  4475.     /* Dump the dimension computations in stack order */
  4476.     for(i = spcnt-1; i >= 0; --i)
  4477.     {
  4478.         do_bracket(iv, spdims[i], spdimsq[i]);
  4479.     }
  4480.     for(i = sacnt-1; i >= 0; --i)
  4481.     {
  4482.         do_bracket(iv, sadims[i], sadimsq[i]);
  4483.     }
  4484.  
  4485.     /* Dump the nested elements in the order encountered */
  4486.     for(i = 0; i < elemcnt; ++i)
  4487.     {
  4488.         do_something(iv, elem[i]);
  4489.     } 
  4490.  
  4491.     /* Dump the remainder of the bracket */
  4492.     p = sp;
  4493.     elemcnt = sacnt = spcnt = 0;
  4494.     p = POP->next;
  4495.      while(p < q)
  4496.     {
  4497.     unsigned char opcode = *p;
  4498.         if(opcode == arraydimsop)
  4499.             p = ((Pop)sadimsq[sacnt++])->next;
  4500.         else if(opcode == ptrdimsop)
  4501.             p = ((Pop)spdimsq[spcnt++])->next;
  4502.         else if(opcode==arrayelemop || opcode==ptrelemop || opcode==strelemop)
  4503.             p = ((Pop)elemq[elemcnt++])->next;
  4504.         else
  4505.             p = do_something(iv, p);
  4506.     }
  4507.     return ((Pop)q)->next;
  4508. }
  4509. static int
  4510. funcret_used(PopT op, unsigned char *p)
  4511. {
  4512. long tmpnum;
  4513.     if(        op->dtype == 0
  4514.         &&    op->dsize == 0)
  4515.     {
  4516.         return 1;                        /* void function */
  4517.     }
  4518.     tmpnum = op->tmpnum;
  4519.  
  4520.     while(*p != funcexitop)
  4521.     {
  4522.         if(*p && *p <= (unsigned char)100)
  4523.         {
  4524.         unsigned char *qp = p+8;
  4525.             if(*p == callfuncop)
  4526.             {/* function using same temp */
  4527.                 if(GL(((PopT)qp)->tmpnum) == tmpnum)
  4528.                 {
  4529.                     return 1;        /* not used earlier */
  4530.                 }
  4531.             }
  4532.             else
  4533.             {
  4534.                 if((p[1]&0xe0) == OPRET)
  4535.                 {
  4536.                      if(GL(((PopT)qp)->tmpnum) == tmpnum)
  4537.                     {
  4538.                         return 0;            /* ret used */
  4539.                     }
  4540.                 }                
  4541.                 qp += p[1]&0x1f;
  4542.                 if((p[2]&0xe0) == OPRET)
  4543.                 {
  4544.                     if(GL(((PopT)qp)->tmpnum) == tmpnum)
  4545.                     {
  4546.                         return 0;            /* ret used */
  4547.                     }
  4548.                 }
  4549.                 qp += p[2]&0x1f;
  4550.                 if((p[3]&0xe0) == OPRET)
  4551.                 {
  4552.                     if(GL(((PopT)qp)->tmpnum) == tmpnum)
  4553.                     {
  4554.                         return 0;            /* ret used */
  4555.                     }
  4556.                 }
  4557.             }
  4558.         }
  4559.         p = POP->next;
  4560.     }
  4561.     return 1;                    /* ret not used */
  4562. }
  4563. static unsigned char
  4564. check_for_builtin(Piv iv, unsigned char *p, int flag)
  4565. {
  4566. short symnum;
  4567. long key[2];
  4568. unsigned char *result;
  4569.  
  4570.     if(flag == 0)
  4571.     {
  4572.         symnum = GS(((PopA)(p+20))->symnum);
  4573.     }
  4574.     else if(flag == 1)
  4575.     {
  4576.         symnum = GS(((PopI)(p+16))->s.symnum);
  4577.     }
  4578.     else if(flag == 2)
  4579.     {
  4580.         symnum = GS(POPI->s.symnum);
  4581.     }
  4582.     else return 0;
  4583.  
  4584.     key[0] = symnum;
  4585.     key[1] = 0;
  4586.     if(SymFind(iv->builtintbl, key, &result))
  4587.         return *result;
  4588.     return 0;
  4589. }
  4590. static void *
  4591. do_funcall(Piv iv, unsigned char *p)
  4592. {/* Arrange output for the stack machine */
  4593. char obuf[4];
  4594. void *sp = p;
  4595. unsigned char *q = skip_bracket(p);
  4596. int argcnt, i, dump;
  4597. void *argloads[100];
  4598. void *argloadsq[100];
  4599. char *callop = 0;
  4600. unsigned char builtin = 0;
  4601.  
  4602.     /* Scan over the bracket and pick up argument loads */
  4603.     argcnt = 0;
  4604.     p = POP->next;
  4605.     while(p < q)
  4606.     {
  4607.         if(*p == getvalop && callop == 0)
  4608.         {
  4609.             builtin = check_for_builtin(iv, p, 0);
  4610.         }
  4611.         else if(*p == callfuncop)
  4612.             callop = p;
  4613.         else if(*p == argloadop)
  4614.         {
  4615.         void *qq = skip_bracket(p);
  4616.             argloads[argcnt] = p;
  4617.             argloadsq[argcnt++] = qq;
  4618.             p = qq;
  4619.         }
  4620.         p = POP->next;
  4621.     }
  4622.  
  4623.     /* Check out whether the function return is used */
  4624.     dump = funcret_used((PopT)(callop+8), q);
  4625.  
  4626.     /* Calling an interpreter builtin ?? */
  4627.     if(builtin)
  4628.     {
  4629.         iv->in_builtin = 1;
  4630.  
  4631.         /* Dump the argument loads in order */
  4632.         /* The ARG instruction will be suppressed because iv->in_builtin > 0 */
  4633.         for(i = 0; i < argcnt; ++i)
  4634.         {
  4635.             do_bracket(iv, argloads[i], argloadsq[i]);
  4636.         }
  4637.         iv->stackdepth -= argcnt;
  4638.  
  4639.         /* Generate the BUILTIN instruction */
  4640.         i = 3;
  4641.         ++iv->stackdepth;
  4642.         obuf[0] = XTD;
  4643.         obuf[1] = BUILTIN;
  4644.         obuf[2] = builtin;
  4645.         if(dump)
  4646.         {
  4647.             obuf[3] = DUMP;
  4648.             --iv->stackdepth;
  4649.             i = 4;
  4650.         }
  4651.         write_obuf(iv, obuf, i);
  4652.         iv->in_builtin = 0;
  4653.     }
  4654.     else
  4655.     {
  4656.         /* Generate the CALLSETUP instruction */
  4657.         p = sp;
  4658.         p = POP->next;
  4659.         while(p < q)
  4660.         {
  4661.             if(*p == argloadop)
  4662.                 break;
  4663.             else
  4664.                 p = do_something(iv, p);
  4665.         }            
  4666.  
  4667.         /* Dump the argument loads in order */
  4668.         for(i = 0; i < argcnt; ++i)
  4669.         {
  4670.             do_bracket(iv, argloads[i], argloadsq[i]);
  4671.         }
  4672.         /* Generate the CALL instruction */
  4673.         i = 1;
  4674.         obuf[0] = CALL;
  4675.         if(dump)
  4676.         {
  4677.             obuf[1] = DUMP;
  4678.             --iv->stackdepth;
  4679.             i = 2;
  4680.         }
  4681.         write_obuf(iv, obuf, i);
  4682.         if((GL(((Pop)(callop))->data1) & 0xff) == D_STRUCT)
  4683.         {
  4684.             ++iv->has_structret;
  4685.         }
  4686.     }
  4687.     return ((Pop)q)->next;
  4688. }
  4689. static void *
  4690. do_expr(Piv iv, unsigned char *p)
  4691. {
  4692. unsigned char *q = skip_bracket(p);
  4693.  
  4694.     if(iv->debug >= '2')
  4695.         cfeprintf("EXPR inst(%u) `%s'\n", *p, oxgenops[*p]);
  4696.  
  4697.     while(p < q)
  4698.     {
  4699.         switch(*p)
  4700.         {
  4701.             case    arrayelemop:
  4702.                 p = do_arrayelem(iv, p);
  4703.                 break;
  4704.             case    strelemop:
  4705.                 p = do_strelem(iv, p);
  4706.                 break;
  4707.             case    ptrelemop:
  4708.                 p = do_ptrelem(iv, p);
  4709.                 break;
  4710.             case    funcallop:
  4711.                 p = do_funcall(iv, p);
  4712.                 break;
  4713.             case    condop:
  4714.             case    twopathop:
  4715.             case    logicalop:
  4716.             case    binopop:
  4717.             case    argloadop:
  4718.             case    preincrdecop:
  4719.             case    postincrdecop:
  4720.             case    compoundop:
  4721.             case    unopop:
  4722.                 p = POP->next;
  4723.                 break;
  4724.             default:
  4725.                 p = do_something(iv, p);
  4726.                 break;
  4727.         }
  4728.     }
  4729.     return ((Pop)q)->next;
  4730. }
  4731. static void *
  4732. do_expstmt(Piv iv, unsigned char *p)
  4733. {
  4734. unsigned char *q = skip_bracket(p);
  4735.  
  4736.     p = POP->next;
  4737.     while(p < q)
  4738.     {
  4739.       p = do_something(iv, p);
  4740.     }
  4741.     return q;
  4742. }
  4743. static void *
  4744. do_ifstmt(Piv iv, unsigned char *p)
  4745. {
  4746. unsigned char *q = skip_bracket(p);
  4747.  
  4748.     p = POP->next;
  4749.     while(p < q)
  4750.     {
  4751.       p = do_something(iv, p);
  4752.     }
  4753.  
  4754.     return ((Pop)q)->next;
  4755. }
  4756. static void *
  4757. do_ifelsestmt(Piv iv, unsigned char *p)
  4758. {
  4759. unsigned char *q = skip_bracket(p);
  4760.  
  4761.     p = POP->next;
  4762.     while(p < q)
  4763.     {
  4764.       p = do_something(iv, p);
  4765.     }
  4766.  
  4767.     return ((Pop)q)->next;
  4768. }
  4769. static void *
  4770. do_switchstmt(Piv iv, unsigned char *p)
  4771. {
  4772. unsigned char *q = skip_bracket(p);
  4773.  
  4774.     p = POP->next;
  4775.     while(p < q)
  4776.     {
  4777.       p = do_something(iv, p);
  4778.     }
  4779.  
  4780.     return ((Pop)q)->next;
  4781. }
  4782. static void *
  4783. do_whilestmt(Piv iv, unsigned char *p)
  4784. {
  4785. unsigned char *q = skip_bracket(p);
  4786.  
  4787.     p = POP->next;
  4788.     while(p < q)
  4789.     {
  4790.       p = do_something(iv, p);
  4791.     }
  4792.     return ((Pop)q)->next;
  4793. }
  4794. static void *
  4795. do_dostmt(Piv iv, unsigned char *p)
  4796. {
  4797. unsigned char *q = skip_bracket(p);
  4798.  
  4799.     p = POP->next;
  4800.     while(p < q)
  4801.     {
  4802.       p = do_something(iv, p);
  4803.     }
  4804.     return ((Pop)q)->next;
  4805. }
  4806. static void *
  4807. do_forstmt(Piv iv, unsigned char *p)
  4808. {
  4809. unsigned char *q = skip_bracket(p);
  4810.  
  4811.     p = POP->next;
  4812.     while(p < q)
  4813.     {
  4814.       p = do_something(iv, p);
  4815.     }
  4816.     return ((Pop)q)->next;
  4817. }
  4818. static void *
  4819. do_asmstmt(Piv iv, unsigned char *p)
  4820. {
  4821. unsigned char *q = skip_bracket(p);
  4822.  
  4823.     p = POP->next;
  4824.     while(p < q)
  4825.     {
  4826.       p = do_something(iv, p);
  4827.     }
  4828.     return ((Pop)q)->next;
  4829. }
  4830. static void *
  4831. do_initstmt(Piv iv, unsigned char *p)
  4832. {
  4833. unsigned char *q = skip_bracket(p);
  4834.  
  4835.     p = POP->next;
  4836.     while(p < q)
  4837.     {
  4838.       p = do_something(iv, p);
  4839.     }
  4840.     return ((Pop)q)->next;
  4841. }
  4842. static void *
  4843. do_anfblock(Piv iv, unsigned char *p)
  4844. {
  4845. unsigned char *q = skip_bracket(p);
  4846.  
  4847.     p = POP->next;
  4848.     while(p < q)
  4849.     {
  4850.       p = do_something(iv, p);
  4851.     }
  4852.     return ((Pop)q)->next;
  4853. }
  4854. static char *
  4855. nodot(Piv iv, char *name)
  4856. {
  4857. char *cp;
  4858.     if((cp = strchr(name, '.')))
  4859.     {
  4860.     char *newname;
  4861.         newname = Cmalloc(iv->category, strlen(name)+1);
  4862.         strcpy(newname,name);
  4863.         cp = strchr(newname, '.');
  4864.         *cp = 0;
  4865.         return newname;
  4866.     }
  4867.     return name;
  4868. }
  4869. static void
  4870. printfunc(Piv iv, unsigned char *p)
  4871. {
  4872. char *funcname = nodot(iv, iv->symaddr[GS(POPI->funcdef.symnum)]);
  4873.  
  4874.     if(*p == gfuncdefop)
  4875.     {
  4876.         fprintf(iv->outfile, "\n%8.8lx:    .global .function _%s\n",
  4877.             iv->out_offset, funcname);
  4878.     }
  4879.     else if(*p == sfuncdefop)
  4880.     {
  4881.         fprintf(iv->outfile, "\n%8.8lx:    .local .function _%s\n", 
  4882.             iv->out_offset, funcname);
  4883.     }
  4884. }
  4885. static void *
  4886. do_stmt(Piv iv, unsigned char *p)
  4887. {
  4888. void *q;
  4889.  
  4890.     if(iv->debug >= '2')
  4891.         cfeprintf("STMT inst(%u) `%s'\n", *p, oxgenops[*p]);
  4892.  
  4893.     q = POP->next;
  4894.  
  4895.     switch(*p)
  4896.     {
  4897.         case labelop:
  4898.             newlabel_insert(iv, GL( POP->data));
  4899.             break;
  4900.         case gfuncdefop:
  4901.         case sfuncdefop:
  4902.         case funcexitop:
  4903.             PERROR(pName ":ERROR: Malformed input file1=%u=%p",*p, p);
  4904.         case nestedfuncdefop:
  4905.         {
  4906.             if(iv->listing_wanted)
  4907.             {
  4908.             char obuf[8];
  4909.                 obuf[0] = NFUNC;
  4910.                 *((char**)&obuf[1]) = nodot(iv, iv->symaddr[GS(POPI->funcdef.symnum)]);
  4911.                 write_obuf(iv, obuf, 5);
  4912.             }
  4913.             iv->numnested += 1;
  4914.             break;
  4915.         }
  4916.         case nestedfuncexitop:
  4917.         {
  4918.         char obuf[2];
  4919.             obuf[0] = RET;
  4920.             write_obuf(iv, obuf, 1);
  4921.             break;        
  4922.         }
  4923.         case anfblockop:
  4924.             q = do_anfblock(iv, p);
  4925.             break;
  4926.         case expstmtop:
  4927.             q = do_expstmt(iv, p);
  4928.             break;
  4929.         case ifstmtop:
  4930.             q = do_ifstmt(iv, p);
  4931.             break;
  4932.         case ifelsestmtop:
  4933.             q = do_ifelsestmt(iv, p);
  4934.             break;
  4935.         case switchstmtop:
  4936.             q = do_switchstmt(iv, p);
  4937.             break;
  4938.         case whilestmtop:
  4939.             q = do_whilestmt(iv, p);
  4940.             break;
  4941.         case dostmtop:
  4942.             q = do_dostmt(iv, p);
  4943.             break;
  4944.         case forstmtop:
  4945.             q = do_forstmt(iv, p);
  4946.             break;
  4947.         case asmstmtop:
  4948.             q = do_asmstmt(iv, p);
  4949.             break;
  4950.         case initstmtop:
  4951.             q = do_initstmt(iv, p);
  4952.             break;
  4953.         case lineop:
  4954.             if(iv->debug >= '3')
  4955.             {
  4956.                 cfeprintf("Line=%u depth=%d\n", GL(POP->data), iv->stackdepth);
  4957.             }
  4958.             if(iv->listing_wanted)
  4959.             {
  4960.             char obuf[8];
  4961.                 obuf[0] = LINENO;
  4962.                 *((long*)&obuf[1]) = GL(POP->data);
  4963.                 write_obuf(iv, obuf, 5);
  4964.             }
  4965.             iv->lastline = GL(POP->data);
  4966.             break;
  4967.         default:
  4968.             break;
  4969.     }
  4970.     return q;
  4971. }
  4972. static void *
  4973. do_something(Piv iv, unsigned char *p)
  4974. {
  4975.     if(*p < labelop)
  4976.         return decode_anf(iv, p);
  4977.     else if(*p >= condop && *p < symbop)
  4978.         return do_expr(iv, p);
  4979.     else
  4980.         return do_stmt(iv, p);
  4981. }
  4982. static void
  4983. do_bracket(Piv iv, unsigned char *p, unsigned char *q)
  4984. {
  4985.     p = POP->next;
  4986.     while(p < q)
  4987.     {
  4988.       p = do_something(iv, p);
  4989.     }
  4990. }
  4991. static void *
  4992. dumpa_func(Piv iv, unsigned char *p)
  4993. {
  4994. unsigned char obuf[2];
  4995. Pafile pf;
  4996. unsigned char *pdef = p;
  4997.  
  4998.     iv->ob = new_nodeO(iv);        /* setup first intermediate output node */
  4999.     link_ob(iv);                /* null node never unlinked */
  5000.     iv->first_ob = iv->ob_usedtail;
  5001.  
  5002.     iv->cod = new_nodeC(iv);    /* setup first code node */
  5003.     link_cod(iv);                /* null node never unlinked */
  5004.     iv->first_cod = iv->cod_usedtail;
  5005.  
  5006.     pf = iv->files[iv->filenum];
  5007.     if(iv->listing_wanted)
  5008.     {
  5009.         printfunc(iv, p);
  5010.     }
  5011.     p = POP->next;
  5012.  
  5013.     for(;;)
  5014.     {
  5015.         if(*p == funcexitop)
  5016.         {
  5017.             obuf[0] = RET;
  5018.             write_obuf(iv, obuf, 1);
  5019.             write_funcdata(iv, pdef);
  5020.             break;
  5021.         }
  5022.         else
  5023.             p = do_something(iv, p);
  5024.     }
  5025.     save_extlocs(iv);
  5026.     reset_funcdata(iv);
  5027.     return p;
  5028. }
  5029. static void
  5030. dump_funcs(Piv iv)
  5031. {
  5032. long pad;
  5033. Pafile pf;
  5034. unsigned char *p;
  5035. int i;
  5036.  
  5037. #if 0
  5038. oxcc_debug(__builtin_iv(),0x40040);
  5039. #endif
  5040.  
  5041.     reset_funcdata(iv);
  5042.     for(i = 0; i < iv->numfiles; ++i)
  5043.     {
  5044.         iv->filenum = i;
  5045.         pf = iv->files[i];
  5046.         p = pf->file_p;
  5047.         if(iv->listing_wanted)
  5048.             fprintf(iv->outfile, "\n\nFile:%s:\n\n", pf->symaddr[1]);
  5049.  
  5050.         while(*p != endfileop)
  5051.         {
  5052.             if(*p == labelop)
  5053.             {
  5054.                 newlabel_insert(iv, GL( POP->data ));
  5055.             }
  5056.             else if(*p == lineop)
  5057.             {
  5058.                 iv->lastline = GL(POP->data);
  5059.                 if(iv->debug >= '3')
  5060.                 {
  5061.                     cfeprintf("Line=%u depth=%d\n", iv->lastline, iv->stackdepth);
  5062.                 }
  5063.                 if(iv->listing_wanted)
  5064.                     fprintf(iv->outfile, "Line:%ld:\n", iv->lastline);
  5065.             }
  5066.             else if(*p == gfuncdefop || *p == sfuncdefop)
  5067.             {
  5068.                 p = dumpa_func(iv, p);
  5069.             }
  5070.             else if(*p == anfblockop)
  5071.             {
  5072.                 PERROR(pName ": Sorry, Outer anf blocks not handled.\n");
  5073.             }
  5074.             p = POP->next;;
  5075.         }
  5076.     }
  5077.  
  5078.     /* Start the data area on an 8 byte boundary */
  5079.     if((pad = iv->out_offset & 7))
  5080.         pad = 8-pad;
  5081.     iv->out_offset += pad;
  5082.  
  5083.     if(pad && !iv->listing_wanted)
  5084.         FILEWRITE(padit, pad);
  5085.     iv->header->a_text = iv->out_offset;
  5086. }
  5087. static void
  5088. fix_thunks(Piv iv)
  5089. {
  5090. Pafile pf;
  5091. int i;
  5092. unsigned char **vp;
  5093. unsigned char *p;
  5094.  
  5095.     for(i = 0; i < iv->numfiles; ++i)
  5096.     {
  5097.         iv->filenum = i;
  5098.         pf = iv->files[i];
  5099.         if(SymHead(pf->datatbl))
  5100.         {
  5101.             while(SymNext(pf->datatbl))
  5102.             {
  5103.                 SymValue(pf->datatbl, &vp);
  5104.                 p = vp[1];
  5105.                 if(*p == thunkblockop)
  5106.                 {/* rearrange the FUNCTHUNK */
  5107.                 unsigned short mods;
  5108.                     mods = GS(POP->data7);
  5109.                     mods &= 0xc000;
  5110.                     mods |= GS(POP->data9) & 0x1f1f;
  5111.                     PS( POP->data7 ) = mods;
  5112.                     PS( POP->data9) = get_maxdepth(iv, GS( POP->data2 ));
  5113.                     if(mods & Fextern)
  5114.                     {/* Put symbol number in the offset slot */
  5115.                         PL( POP->data5 ) = final_symnum(iv, GS( POP->data2 ));
  5116.                     }
  5117.                     else
  5118.                     {/* Put function offset in the offset slot */
  5119.                         PL( POP->data5 ) = newlabel_fix(iv, GL( POP->data5 ));
  5120.                     }
  5121.                 }
  5122.             }
  5123.         }
  5124.     }
  5125. }
  5126. static void
  5127. printdata(Piv iv, char *sym, char *msg, void *ptr, int size, 
  5128.     long offset, int locid)
  5129. {
  5130. int x;
  5131.  
  5132.     x = print8(iv, ptr, size, offset, 0);
  5133.     if(locid > 0)
  5134.         fprintf(iv->outfile,"  _%s.%d (%s)\n", sym, locid, msg);
  5135.     else
  5136.         fprintf(iv->outfile,"  _%s (%s)\n", sym, msg);
  5137.     while((size -= x) > 0)
  5138.     {
  5139.         offset += x;
  5140.         ((char*)ptr) += x;
  5141.         x = print8(iv, ptr, size, offset, 1);
  5142.     }
  5143. }
  5144. static void
  5145. printbss(Piv iv, char *sym, int size, int offset, unsigned char prevopcode,
  5146.                                 int locid)
  5147. {
  5148.     if(prevopcode == globssop)
  5149.       fprintf(iv->outfile, "%8.8x:  _%s (BSS %d)\n", offset, sym, size);
  5150.     else
  5151.       fprintf(iv->outfile, "%8.8x:  _%s.%d (bss %d)\n", offset, sym, locid, size);
  5152. }
  5153. static void
  5154. dump_data(Piv iv)
  5155. {
  5156. struct _val {
  5157. unsigned long size;
  5158. unsigned char *p;
  5159. unsigned char *prevp;
  5160. long locid;
  5161. };
  5162. struct _val *val;
  5163. unsigned long *key;
  5164. long datsize = 0;
  5165. long bsssize = 0;
  5166. long curr_offset = iv->out_offset;
  5167. unsigned char opcode, prevopcode = 0;
  5168.  
  5169.     if(SymHead(iv->datatbl))
  5170.     {
  5171.     void *savaddr;
  5172.         if(iv->listing_wanted)
  5173.         {
  5174.             fprintf(iv->outfile, "\n\t.data\n\n");
  5175.             savaddr = iv->symaddr[0];
  5176.             iv->symaddr[0] = "STRING_";
  5177.         }
  5178.         while(SymNext(iv->datatbl))
  5179.         {
  5180.         unsigned char *p;
  5181.         long size;
  5182.         long pad;
  5183.             SymKey(iv->datatbl, &key);
  5184.             SymValue(iv->datatbl, &val);
  5185.             p = val->p;
  5186.             opcode = *p;
  5187.             if(val->prevp)
  5188.                 prevopcode = *(val->prevp);
  5189.             size = val->size;
  5190.             if((pad = size & 3))  /* the interpreter requires 4 byte alignment */
  5191.                 pad = 4-pad;
  5192.  
  5193.             if(        opcode == datablockop
  5194.                 ||    opcode == mallocblockop
  5195.                 ||  opcode == thunkblockop
  5196.                 ||    opcode == stringblockop)
  5197.             {
  5198.                 if(iv->listing_wanted)
  5199.                 {
  5200.                 char *msg;
  5201.  
  5202.                     if(        opcode == datablockop
  5203.                         ||    opcode == stringblockop)
  5204.                     {
  5205.                         if(prevopcode == glodatop)
  5206.                             msg = "DATA";
  5207.                         else
  5208.                         {
  5209.                             msg = "data";
  5210.                         }
  5211.                     }
  5212.                     else if(opcode == mallocblockop)
  5213.                     {
  5214.                         msg = "alloced";
  5215.                     }
  5216.                     else /* thunkblockop */
  5217.                     {
  5218.                         if(prevopcode == extfuncop)
  5219.                         {
  5220.                         long bu;
  5221.                             if((bu = check_for_builtin(iv, p, 2)))
  5222.                             {
  5223.                             Pft ft = (Pft)(p+24);
  5224.                                 ft->funcaddr = bu;
  5225.                                 ft->fmods |= Fbuiltin;
  5226.                                 ft->fmods &= ~Fextern;
  5227.                                 *(val->prevp) = 0xff;
  5228.                                 msg = "thunk";
  5229.                             }
  5230.                             else
  5231.                                 msg = "EXTHUNK";
  5232.                         }
  5233.                         else if(prevopcode == glofuncop)
  5234.                             msg = "THUNK";
  5235.                         else
  5236.                         {
  5237.                             msg = "thunk";
  5238.                         }
  5239.                     }
  5240.                     printdata(iv, iv->symaddr[GS(POP->data2)], 
  5241.                             msg, p+24, size, GL(POP->data1), val->locid);
  5242.                 }
  5243.                 else
  5244.                 {
  5245.                     if(opcode == thunkblockop)
  5246.                     {
  5247.                         if(prevopcode == extfuncop)
  5248.                         {
  5249.                         long bu;
  5250.                             if((bu = check_for_builtin(iv, p, 2)))
  5251.                             {
  5252.                             Pft ft = (Pft)(p+24);
  5253.                                 ft->funcaddr = bu;
  5254.                                 ft->fmods |= Fbuiltin;
  5255.                                 ft->fmods &= ~Fextern;
  5256.                                 *(val->prevp) = 0xff;
  5257.                             }
  5258.                         }
  5259.                     }
  5260.                     FILEWRITE(p+24, size);
  5261.                     if(pad > 0)
  5262.                         FILEWRITE(padit, pad);
  5263.                 }
  5264.                 datsize += size+pad;
  5265.                 iv->out_offset += size+pad;
  5266.             }
  5267.             else if(opcode == bssblockop)
  5268.             {
  5269.                 if(iv->listing_wanted)
  5270.                 {
  5271.                     printbss(iv, iv->symaddr[GS(POP->data2)], size, 
  5272.                         GL(POP->data1), prevopcode, val->locid);
  5273.                 }
  5274.                 bsssize += size+pad;
  5275.             }
  5276.         }
  5277.         if(iv->listing_wanted)
  5278.         {
  5279.             iv->symaddr[0] = savaddr;
  5280.         }
  5281.     }
  5282.     iv->header->a_data = iv->out_offset - curr_offset;
  5283.     if(datsize != iv->header->a_data)
  5284.         PERROR(pName,":SYSERROR: data size incorrect (%d)!=(%d)\n",
  5285.             datsize, iv->header->a_data);
  5286. }
  5287. static void
  5288. dump_bss(Piv iv)
  5289. {
  5290.     iv->header->a_bss = iv->total_size - iv->bss_offset;
  5291. }
  5292. static void
  5293. make_final_string_pack(Piv iv)
  5294. {
  5295. long strsize = 0;
  5296. int strcnt = 0;
  5297. char *pack;
  5298. char *cp;
  5299. struct {
  5300.     char *str;
  5301.     long symnum;
  5302.     long symofs;
  5303. } *val;
  5304.  
  5305.     if(SymHead(iv->finalsymtbl))
  5306.     {
  5307.         while(SymNext(iv->finalsymtbl))
  5308.         {
  5309.             SymValue(iv->finalsymtbl, &val);
  5310.             ++strcnt;
  5311.             val->symofs = strsize+4;
  5312.             strsize += strlen(val->str)+2;
  5313.         }
  5314.     }
  5315.     pack = Ccalloc(iv->category, 1, strsize+4);
  5316.     *((long*)pack) = strsize + 4;
  5317.     cp = pack + 4;
  5318.     if(SymHead(iv->finalsymtbl))
  5319.     {
  5320.         while(SymNext(iv->finalsymtbl))
  5321.         {
  5322.             SymValue(iv->finalsymtbl, &val);
  5323.             *cp++ = '_';
  5324.             strcpy(cp, val->str);
  5325.             cp += strlen(val->str)+1;
  5326.         }
  5327.     }
  5328.     iv->finalstringpack = pack;
  5329.     iv->finalpacksize = strsize+4;
  5330. }
  5331. static unsigned char *
  5332. dump_switch(Piv iv, unsigned char *p, int filenum)
  5333. {
  5334. struct nlist nl;
  5335. unsigned char *q = skip_bracket(p);
  5336.  
  5337.     nl.n_type = N_SWTAB;
  5338.     nl.n_other = 0;
  5339.     while(p < q)
  5340.     {
  5341.         if(*p == switchidop)
  5342.         {
  5343.             nl.n_desc = GS(POP->data1);    /* id */
  5344.         }
  5345.         else if(*p == casevalop)
  5346.         {
  5347.         long key[2];
  5348.         long *result;
  5349.             nl.n_un.n_strx = GL(POP->data1);    /* value */
  5350.             key[0] = GL(POP->data); /* label number */
  5351.             key[1] = filenum;
  5352.             if(SymFind(iv->newlabeltbl, &key, &result))
  5353.             {
  5354.                 nl.n_value = *result;            /* offset */
  5355.             }
  5356.             else
  5357.             {
  5358.                 PERROR(pName ":SYSERROR: case label not found\n");
  5359.             }
  5360.             if(iv->listing_wanted)
  5361.             {
  5362.                 /* print nothing */
  5363.             }
  5364.             else
  5365.             {
  5366.                 FILEWRITE(&nl, sizeof(struct nlist));
  5367.                 iv->out_offset += sizeof(struct nlist);
  5368.             }
  5369.         }
  5370.         p = POP->next;
  5371.     }
  5372.     return ((Pop)q)->next;
  5373. }
  5374. static void
  5375. dump_symbols(Piv iv)
  5376. {
  5377. long curr_offset = iv->out_offset;
  5378. int i;
  5379. struct nlist nl;
  5380.  
  5381.      nl.n_other = 0;
  5382.     nl.n_desc = 0;
  5383.  
  5384.     make_final_string_pack(iv);
  5385.  
  5386.     if(SymHead(iv->gbltbl))
  5387.     {
  5388.         if(iv->listing_wanted)
  5389.         {
  5390.             fprintf(iv->outfile, "\n\t.symbols\n\n");
  5391.         }
  5392.         while(SymNext(iv->gbltbl))
  5393.         {
  5394.         struct _gloval *valp;
  5395.         unsigned char opcode;
  5396.  
  5397.             SymValue(iv->gbltbl, &valp);
  5398.             if((opcode = *(valp->p)))
  5399.             {
  5400.             PopI pp;
  5401.                 pp = (PopI) (((Pop)(valp->p))->next+8);
  5402.                 nl.n_un.n_strx = final_strofs(iv, valp->symname);
  5403.                 if(opcode == glodatop)
  5404.                 {
  5405.                     nl.n_type = N_DATA|N_EXT;
  5406.                     nl.n_value = pp->s.offset + iv->header->a_text;
  5407.                 }
  5408.                 else if(opcode == globssop)
  5409.                 {
  5410.                     nl.n_type = N_BSS|N_EXT;
  5411.                     nl.n_value = pp->s.offset + iv->header->a_text;
  5412.                 }
  5413.                 else if(opcode == glofuncop || opcode == extfuncop)
  5414.                 {/* The symbol is really a thunk in the data section */
  5415.                     nl.n_type = N_NDC|N_EXT;
  5416.                     nl.n_value = pp->s.offset;
  5417.                 }
  5418.                 else if(opcode == extvarop)
  5419.                 {
  5420.                     nl.n_type = N_UNDF|N_EXT;
  5421.                     nl.n_value = 0;
  5422.                 }
  5423.                 else if(opcode == 0xff)
  5424.                 {/* Builtin thunk */
  5425.                     continue;
  5426.                 }
  5427.                 if(iv->listing_wanted)
  5428.                 {
  5429.                 int symval = nl.n_value;
  5430.                     if(nl.n_type & (N_DATA|N_BSS))
  5431.                         symval -= iv->header->a_text;
  5432.                     fprintf(iv->outfile, "%8.8x:  _%s\n", symval, valp->symname);
  5433.                 }
  5434.                 else
  5435.                 {
  5436.                     FILEWRITE(&nl, sizeof(struct nlist));
  5437.                 }
  5438.                 iv->out_offset += sizeof(struct nlist);
  5439.             }
  5440.         }
  5441.     }
  5442.     /* DUMP SWITCH TABLE INFO */
  5443.     for(i = 0; i < iv->numfiles; ++i)
  5444.     {
  5445.     Pafile pf = iv->files[i];
  5446.     unsigned char *p;
  5447.         if((p = pf->switch_p))
  5448.         {
  5449.             while(*p != endfileop)
  5450.             {
  5451.                 if(*p == switchidop)
  5452.                 {
  5453.                     p = dump_switch(iv, p, i);
  5454.                 }
  5455.                 else p = POP->next;
  5456.             }
  5457.         }
  5458.     }
  5459.     iv->header->a_syms = iv->out_offset - curr_offset;;
  5460. }/* END: dump_symbols() */
  5461.  
  5462. static void
  5463. dump_text_relocs(Piv iv)
  5464. {
  5465. long curr_offset = iv->out_offset;
  5466. PEL pel = iv->finextbufstart;
  5467. struct relocation_info r;
  5468.  
  5469.     r.r_pcrel = 0;
  5470.     r.r_extern = 1;
  5471.     r.r_length = 2;
  5472.     r.r_pad = 0;
  5473.     if(pel && iv->listing_wanted)
  5474.     {
  5475.         fprintf(iv->outfile,"\n\t.textrels\n\n");
  5476.     }
  5477.     while(pel)
  5478.     {
  5479.         r.r_symbolnum = final_symnum(iv, pel->symnum);
  5480.         r.r_address = pel->spot;
  5481.         if(pel->symnum > 0)
  5482.         {
  5483.             if(iv->listing_wanted)
  5484.             {
  5485.                 fprintf(iv->outfile,"%8.8lx: .extern _%s\n", 
  5486.                     r.r_address, iv->symaddr[pel->symnum]);
  5487.             }
  5488.             else
  5489.             {
  5490.                 FILEWRITE(&r, sizeof(struct relocation_info));
  5491.             }
  5492.             iv->out_offset += sizeof(struct relocation_info);
  5493.         }
  5494.         pel = pel->next;
  5495.     }
  5496.     iv->header->a_trsize = iv->out_offset - curr_offset;
  5497.  
  5498. }/* END: dump_text_relocs() */
  5499.  
  5500. static void
  5501. dump_data_relocs(Piv iv)
  5502. {
  5503. long curr_offset = iv->out_offset;
  5504. struct relocation_info r;
  5505.  
  5506.     r.r_pcrel = 0;
  5507.     r.r_length = 2;
  5508.     r.r_pad = 0;
  5509.     if(SymHead(iv->reloctbl))
  5510.     {
  5511.         if(iv->listing_wanted)
  5512.         {
  5513.             fprintf(iv->outfile,"\n\t.datarels\n\n");
  5514.         }
  5515.         while(SymNext(iv->reloctbl))
  5516.         {
  5517.         struct _rkey *kp;
  5518.         struct _rval *vp;
  5519.         unsigned char *p;
  5520.         int symnum;
  5521.           SymKey(iv->reloctbl, &kp);
  5522.           SymValue(iv->reloctbl, &vp);
  5523.           p = vp->p;        /* pointer to relocop in input buffer */
  5524.           symnum = GS(POPI->reloc.rsym);
  5525.  
  5526.           if(kp->rsize == 1)
  5527.               r.r_length = 0;
  5528.           else if(kp->rsize == 2)
  5529.               r.r_length = 1;
  5530.           else if(kp->rsize == 4)
  5531.               r.r_length = 2;
  5532.           else PERROR(pName ":ERROR: reloc size too large\n");
  5533.  
  5534.           r.r_address = GL( POPI->reloc.spot );
  5535.           if(*p == extlocop)
  5536.           {/* External variable */
  5537.             r.r_extern = 1;
  5538.             r.r_symbolnum = final_symnum(iv, symnum);
  5539.           }
  5540.           else if(*p)
  5541.           {
  5542.             r.r_extern = 0;
  5543.             r.r_symbolnum = N_DATA;
  5544.           }
  5545.           if(*p)
  5546.           {
  5547.               if(iv->listing_wanted)
  5548.               {
  5549.                 if(r.r_extern)
  5550.                 {
  5551.                     if(vp->rsym <= 0)
  5552.                     {/* an absolute value */
  5553.                         continue;
  5554.                     }
  5555.                     fprintf(iv->outfile,"%8.8lx: .extern _%s\n",
  5556.                         r.r_address, iv->symaddr[symnum]);
  5557.                 }
  5558.                 else
  5559.                 {
  5560.                     fprintf(iv->outfile, "%8.8lx: .segrel\n", r.r_address);
  5561.                 }
  5562.               }
  5563.               else
  5564.               {
  5565.                   if(r.r_extern && vp->rsym <= 0)
  5566.                   {/* an absolute value */
  5567.                     continue;
  5568.                   }
  5569.                   FILEWRITE(&r, sizeof(struct relocation_info));
  5570.               }
  5571.               iv->out_offset += sizeof(struct relocation_info);
  5572.             }
  5573.         }
  5574.     }
  5575.     iv->header->a_drsize = iv->out_offset - curr_offset;
  5576.  
  5577. }/* END: dump_data_relocs() */
  5578.  
  5579. static void
  5580. prepare_data_relocs(Piv iv)
  5581. {
  5582.     if(SymHead(iv->reloctbl))
  5583.     {
  5584.         while(SymNext(iv->reloctbl))
  5585.         {
  5586.         struct _rkey *kp;
  5587.         struct _rval *vp;
  5588.         unsigned char *p;
  5589.           SymKey(iv->reloctbl, &kp);
  5590.           SymValue(iv->reloctbl, &vp);
  5591.           p = vp->p;        /* pointer to relocop in input buffer */
  5592.  
  5593.           if(*p == extlocop)
  5594.           {/* External variable */
  5595.           }
  5596.           else if(*p)
  5597.           {/* a.out format requires a flat address space for relocations */
  5598.             if(kp->rsize == 1)
  5599.             {
  5600.                 *((char*)vp->base) += iv->header->a_text;
  5601.             }
  5602.             else if(kp->rsize == 2)
  5603.             {
  5604.                 *((short*)vp->base) += iv->header->a_text;
  5605.             }
  5606.             else if(kp->rsize == 4)
  5607.             {
  5608.                 *(vp->base) += iv->header->a_text;
  5609.             }
  5610.             else PERROR(pName ":ERROR: reloc size too large\n");
  5611.  
  5612.           }
  5613.         }
  5614.     }
  5615. }/* END: prepare_data_relocs() */
  5616.  
  5617. static void
  5618. dump_symbol_strings(Piv iv)
  5619. {
  5620.     if(iv->listing_wanted)
  5621.     {
  5622.         /* print nothing */
  5623.     }
  5624.     else
  5625.     {
  5626.         FILEWRITE(iv->finalstringpack, iv->finalpacksize);
  5627.     }
  5628. }/* END: dump_symbol_strings() */
  5629.  
  5630. static int
  5631. gen_output(Piv iv, char *outpath)
  5632. {/* Bytecode output */
  5633. char *cp;
  5634. int i;
  5635. char outname[256];
  5636.     
  5637.     strcpy(outname, outpath);
  5638.     if((cp = strrchr(outname, '.')))
  5639.     {
  5640. #if 0
  5641.       if(iv->listing_wanted)
  5642.         strcpy(cp, ".lst");
  5643.       else
  5644.         strcpy(cp, ".byt");
  5645. #endif
  5646.     }
  5647.     else
  5648.     {
  5649.       if(iv->listing_wanted)
  5650.         strcat(outname, ".lst");
  5651.       else
  5652.         strcat(outname, ".byt");
  5653.     }
  5654.     for(i = 1; i < iv->argc; ++i)
  5655.     {
  5656.       if(!strcmp(outname, iv->argv[i]))
  5657.       {
  5658.         PERROR(pName ":ERROR: output file `%s' is same as input file\n", outname);
  5659.       }
  5660.     }
  5661.     if(!(iv->outfile = fopen(outname, "wb")))
  5662.     {
  5663.         PERROR(pName ":ERROR: Cannot open output file %s\n", outname);
  5664.     }
  5665.  
  5666.     /* Allocate a header struct */
  5667.     iv->header = Ccalloc(iv->category, 1, sizeof(struct exec));
  5668.  
  5669.     if(iv->listing_wanted)
  5670.     {
  5671.     long tim = time(0);
  5672.     char *date = ctime(&tim);
  5673.         fprintf(iv->outfile,"/*\n  `%s'     %s", outname, date);
  5674.         fprintf(iv->outfile,notice,MAJOR_VERSION,MINOR_VERSION);
  5675.     }
  5676.     else
  5677.     {/* Seek past the header area */
  5678.         iv->header->a_info = OMAGIC;
  5679.         fseek(iv->outfile, sizeof(struct exec), SEEK_SET);
  5680.     }
  5681.     install_builtins(iv);
  5682.     make_final_symtab(iv);
  5683.  
  5684. #if 0
  5685. if(iv->debug)
  5686. bterpdebug();
  5687. #endif
  5688.     dump_funcs(iv);
  5689.     fix_thunks(iv);
  5690.     prepare_data_relocs(iv);    /* adjust addresses for flat space */
  5691.     dump_data(iv);
  5692.     dump_bss(iv);
  5693.     dump_text_relocs(iv);
  5694.     dump_data_relocs(iv);
  5695.     dump_symbols(iv);
  5696.     dump_symbol_strings(iv);
  5697.  
  5698.     /* Update the header block */
  5699.     if(!iv->listing_wanted)
  5700.     {
  5701.         fseek(iv->outfile, 0, SEEK_SET);
  5702.         FILEWRITE(iv->header, sizeof(struct exec));
  5703.     }
  5704.     fclose(iv->outfile);
  5705.     iv->outfile = 0;    
  5706.     return iv->errors;
  5707. }
  5708. /* ======================= END BYTECODE OUTPUT GENERATOR ==================== */
  5709.  
  5710. /* ===================== GENERIC CODE BELOW THIS POINT ================== */
  5711. static jmp_buf run_env;
  5712. static void
  5713. prerror(const char *fmt, ...)
  5714. {
  5715.     VFPRINTF(fmt, (char *)(((int *)(&fmt))+1));
  5716.     longjmp(run_env, 3);
  5717. }
  5718. static void
  5719. prwarn(const char *fmt, ...)
  5720. {
  5721.     VFPRINTF(fmt, (char *)(((int *)(&fmt))+1));
  5722. }
  5723. static void
  5724. info(const char *fmt, ...)
  5725. {
  5726.     vfprintf(stdout, fmt, (char *)(((int *)(&fmt))+1));
  5727. }
  5728. /* ========================= MULTI HEAP MALLOC ========================== */
  5729. #define LOCAL static
  5730.  
  5731. #if USING_FRAMEWORK
  5732. #define THEWELL(a) mallocC(local_category, a)
  5733. static int local_category;
  5734. static int num_instance;
  5735. extern void *mallocC(int, int);
  5736. extern void freecat(int);
  5737. extern void oxlink_clear_bss();
  5738. extern int NewMallocCategory();
  5739. #endif /* USING_FRAMEWORK */
  5740.  
  5741. #define BASE_CATEGORY 0
  5742. #define MEMORY_BUG 0
  5743. #define PRINT_RAWDATA 0
  5744.  
  5745. #if MEMORY_BUG == 1
  5746. #define MPRINTF printf
  5747. #else
  5748. #define MPRINTF(args...)
  5749. #endif
  5750.  
  5751. #define PAGESIZE (4096)    /* can use `pagesize' function in OS */
  5752. #define ALIGNMENTM (sizeof(unsigned long))
  5753. #define MAL_MAXLEVEL (12)
  5754. #define ROUNDINGM(a) ((a+(ALIGNMENTM-1))&~(ALIGNMENTM-1))
  5755. #define ALLOCSIZE (4096)
  5756. #define FRNTGUARD (0x544e5246UL)
  5757. #define BACKGUARD (0x48434142UL)
  5758. #ifndef THEWELL
  5759. #define THEWELL do_sbrk
  5760. #endif
  5761.  
  5762. #define NUMTYPES 3
  5763. #define SIZEH 0
  5764. #define FREEH 1
  5765. #define USEDH 2
  5766.  
  5767. #define SKIPVARS NodePM update[MAL_MAXLEVEL+1];NodePM node,prev;int level
  5768.  
  5769. #define DELETENODE(TYPE) \
  5770. {for(level=0;level<=bp->TYPE##level; level++)\
  5771. {if(update[level]->fptr[level] == node)\
  5772. update[level]->fptr[level] = node->fptr[level];else break;}\
  5773. while(bp->TYPE##level>0 && bp->TYPE##header->fptr[bp->TYPE##level]==_NILLL)\
  5774. bp->TYPE##level--;free_Mnode(bp,node,TYPE);}
  5775.  
  5776. #define INSERT() \
  5777. {while(level >= 0){\
  5778. node->fptr[level] = update[level]->fptr[level];\
  5779. update[level]->fptr[level] = node;level--;}}
  5780.  
  5781. #define SETLEVEL(TYPE) \
  5782. {level = getMlevel(bp, bp->TYPE##level);\
  5783. while(bp->TYPE##level < level)update[++bp->TYPE##level]=bp->TYPE##header;}
  5784.  
  5785. #define FINDKEY(TYPE, KEYVAL)\
  5786. {node = bp->TYPE##header;\
  5787. for(level = bp->TYPE##level; level >= 0; level--){\
  5788. while(node->fptr[level]->key < KEYVAL)\
  5789. node = node->fptr[level];\
  5790. update[level] = node;}prev=node;node=node->fptr[0];}
  5791.  
  5792. #define DETACH(SN)\
  5793. {SN->bptr->fptr=SN->fptr;if(SN->fptr)SN->fptr->bptr=SN->bptr;}
  5794.  
  5795. #define UNLINK(SN, N)\
  5796. {if(!sp->fptr&&sp->bptr->bptr<=(AddrP)(MAL_MAXLEVEL+1))dsize[N]=sp->size;\
  5797. DETACH(SN);free_addr(bp,SN);}
  5798.  
  5799. #define CHECKGUARDS(MSG)\
  5800. {if(bp->guarded){\
  5801. unsigned *p2;\
  5802. p2 = (void*)((char*)address+cursize-ALIGNMENTM);\
  5803. if(*address != FRNTGUARD)\
  5804. PERROR(pName #MSG ":%d: corrupted at 0x%x\n", bp->bincat, addr);\
  5805. if(*p2 != BACKGUARD)\
  5806. PERROR(pName #MSG ":%d: corrupted by 0x%x\n", bp->bincat, addr);}}
  5807.  
  5808. #if MEMORY_BUG == 1
  5809. #define HEAPCHECK \
  5810. {void *lastaddr;\
  5811. if(category > 0){\
  5812. guardC(category);\
  5813. if((lastaddr = heapcheckC(category, NULL))){\
  5814. FINDKEY(USEDH, (unsigned)lastaddr-ALIGNMENTM)\
  5815. MPRINTF("bad heap at %x c:%u size=%u\n", lastaddr, category, node->value);\
  5816. (void)print_rawdata(lastaddr-ALIGNMENTM, node->value);\
  5817. abort();}}}
  5818. #else
  5819. #define HEAPCHECK
  5820. #endif
  5821.  
  5822. struct _catlocs {
  5823.     void *addr;
  5824.     struct _catlocs *fptr;
  5825. };
  5826.  
  5827. typedef struct _nodeM
  5828. {
  5829.     unsigned key;
  5830.     unsigned value;
  5831.     unsigned levels;    /* must always be after value */
  5832.     struct _nodeM *fptr[1];
  5833. } NodeM, *NodePM;
  5834.  
  5835. typedef struct _addr
  5836. {
  5837.     struct _addr *fptr;
  5838.     struct _addr *bptr;
  5839.     NodePM maddr;
  5840.     unsigned size;
  5841. } *AddrP;
  5842.  
  5843. struct _bins {
  5844.     unsigned bits;
  5845.     unsigned nbits;
  5846.     NodePM SIZEHheader;
  5847.     int SIZEHlevel;
  5848.     NodePM FREEHheader;
  5849.     int FREEHlevel; 
  5850.     NodePM USEDHheader;
  5851.     int USEDHlevel;
  5852.  
  5853.     unsigned bincat;
  5854.     unsigned maxloc;
  5855.     unsigned minloc;
  5856.     struct _catlocs *catlocs;
  5857.     struct _bins *fptr;
  5858.     NodePM freenodes[NUMTYPES][MAL_MAXLEVEL+2];
  5859.     struct _addr *freeaddrlocs;
  5860.     char *chunkbase[NUMTYPES];
  5861.     int chunksize[NUMTYPES];
  5862.     int guarded;
  5863.     int addrbump;
  5864. };
  5865.  
  5866. static struct _bins zbp;
  5867. static struct _bins *hmap[1009];
  5868. static struct _nodeM _nilll = {0xffffffff,0,0,{0}};
  5869. static struct _nodeM *_NILLL = &_nilll;
  5870. static unsigned maxloc;
  5871. static unsigned minloc;
  5872. static struct _bins *freebinlocs;
  5873. static struct _catlocs *freecatlocs;
  5874. static char *binbase;
  5875. static int binsize;
  5876. static int chunksizes[] = {ALLOCSIZE,3*ALLOCSIZE,2*ALLOCSIZE};
  5877.  
  5878.  
  5879. static long randtbl[32]    = { 0L,
  5880.     0x9a319039L, 0x32d9c024L, 0x9b663182L, 0x5da1f342L, 
  5881.     0xde3b81e0L, 0xdf0a6fb5L, 0xf103bc02L, 0x48f340fbL, 
  5882.     0x7449e56bL, 0xbeb1dbb0L, 0xab5c5918L, 0x946554fdL, 
  5883.     0x8c2e680fL, 0xeb3d799fL, 0xb11ee0b7L, 0x2d436b86L, 
  5884.     0xda672e2aL, 0x1588ca88L, 0xe369735dL, 0x904f35f7L, 
  5885.     0xd7158fd6L, 0x6fa6f051L, 0x616e6b96L, 0xac94efdcL, 
  5886.     0x36413f93L, 0xc622c298L, 0xf5a42ab8L, 0x8a88d77bL, 
  5887.     0xf5ad9d0eL, 0x8999220bL, 0x27fb47b9L
  5888. };
  5889.  
  5890. static  long *fptr    = &randtbl[4];
  5891. static  long *rptr    = &randtbl[1];
  5892.  
  5893. /* ======================== START OF CODE =========================== */
  5894. #if PRINT_RAWDATA == 1
  5895. static char
  5896. hexbyte(unsigned int c)
  5897. {
  5898. char x = c & 0xf;
  5899.  
  5900.     return x + ((x>9) ? 55 : 48);
  5901. }
  5902. static void
  5903. print_rawdata(void *rawdata, long size)
  5904. {
  5905. unsigned long vaddr = 0;
  5906. unsigned char *d = rawdata;
  5907. int i,j;
  5908. char addr[9];
  5909. char hex1[24];
  5910. char hex2[24];
  5911. char side1[9];
  5912. char side2[9];
  5913.  
  5914.     addr[8] = 0;
  5915.     hex1[23] = 0;
  5916.     hex2[23] = 0;
  5917.     side1[8] = 0;
  5918.     side2[8] = 0;
  5919.     while(size > 0)
  5920.     {
  5921.     unsigned long qaddr = vaddr;
  5922.         memset(addr, '0', 8);
  5923.         memset(hex1, ' ', 23);
  5924.         memset(hex2, ' ', 23);
  5925.         memset(side1, ' ', 8);
  5926.         memset(side2, ' ', 8);
  5927.         i = 7;
  5928.         while(qaddr)
  5929.         {
  5930.             addr[i--] = hexbyte(qaddr);
  5931.             qaddr >>= 4;
  5932.         }
  5933.         for(i=0,j=0; i < 8; ++i)
  5934.         {
  5935.             if(--size >= 0)
  5936.             {
  5937.             unsigned int c = *d++;
  5938.                 if(isprint(c))
  5939.                     side1[i] = c;
  5940.                 else
  5941.                     side1[i] = '.';
  5942.                 hex1[j++] = hexbyte(c>>4);
  5943.                 hex1[j++] = hexbyte(c);
  5944.                     ++j;
  5945.             }
  5946.             else break;
  5947.         }
  5948.         for(i=0,j=0; i < 8; ++i)
  5949.         {
  5950.             if(--size >= 0)
  5951.             {
  5952.             unsigned int c = *d++;
  5953.                 if(isprint(c))
  5954.                     side2[i] = c;                    
  5955.                 else
  5956.                     side2[i] = '.';
  5957.                 hex2[j++] = hexbyte(c>>4);
  5958.                 hex2[j++] = hexbyte(c);
  5959.                 ++j;
  5960.             }
  5961.             else break;
  5962.         }
  5963.         VPRINTF("%s  %s%s%s  %s%s%s\n",addr,hex1," | ",hex2,side1,"|",side2);
  5964.         vaddr += 16;
  5965.     }
  5966. }
  5967. #endif
  5968.  
  5969. /*
  5970.  * Returns a really good 31-bit random number.
  5971.  */
  5972. static long
  5973. lrandom()
  5974. {
  5975. long i;
  5976.     
  5977.     *fptr += *rptr;
  5978.     i = (*fptr >> 1) & 0x7fffffffUL;
  5979.     if(++fptr > &randtbl[31])
  5980.     {
  5981.         fptr = &randtbl[1];
  5982.         ++rptr;
  5983.     }
  5984.     else
  5985.     {
  5986.         if(++rptr > &randtbl[31])  
  5987.             rptr = &randtbl[1];
  5988.     }
  5989.     return( i );
  5990. }
  5991. #if !USING_FRAMEWORK
  5992. static void *
  5993. do_sbrk(unsigned amount)
  5994. {
  5995. void *address;
  5996.  
  5997.     address = sbrk(amount);    /* OR WHATEVER TO ACCESS THE OPERATING SYSTEM */
  5998.     if(address == (void*)-1)
  5999.     {
  6000.         PERROR(pName "\nsystem out of memory, requested %u bytes\n", amount);
  6001.     }
  6002.     return address;
  6003. }
  6004. #endif
  6005. static struct _catlocs *
  6006. new_catloc(void)
  6007. {
  6008. struct _catlocs *p;
  6009.     if((p=freecatlocs))
  6010.     {
  6011.         freecatlocs = p->fptr;
  6012.         return p;
  6013.     }
  6014.     if(binsize < sizeof(struct _catlocs))
  6015.     {
  6016.         binbase = THEWELL(4096);
  6017.         binsize = 4096;
  6018.     }
  6019.     binsize -= sizeof(struct _catlocs);
  6020.     p = (void*)binbase;
  6021.     binbase += sizeof(struct _catlocs);
  6022.     return p;
  6023. }
  6024. static void
  6025. free_catloc(struct _catlocs *p)
  6026. {
  6027.     p->fptr = freecatlocs;
  6028.     freecatlocs = p;
  6029. }
  6030. static void *
  6031. new_chunk(struct _bins *bp, int size, int type)
  6032. {
  6033. char *p;
  6034.      if(bp->chunksize[type] < size)
  6035.     {
  6036.         if(bp->bincat == 0) {
  6037.             bp->chunkbase[type] = THEWELL(chunksizes[type]);
  6038.             bp->chunksize[type] = chunksizes[type];
  6039.         }
  6040.         else {
  6041.         struct _catlocs *cl;
  6042.             bp->chunkbase[type] = Cmalloc(0,chunksizes[type]-zbp.guarded);
  6043.             bp->chunksize[type] = chunksizes[type]-zbp.guarded;
  6044.             cl = new_catloc();
  6045.             cl->addr = bp->chunkbase[type];
  6046.             cl->fptr = bp->catlocs;
  6047.             bp->catlocs = cl;
  6048.         }
  6049.     }
  6050.     bp->chunksize[type] -= size;
  6051.     p = bp->chunkbase[type];
  6052.     bp->chunkbase[type] += size;
  6053.     return p;
  6054. }
  6055. static void *
  6056. new_Mnode(struct _bins *bp, int levels, int type)
  6057. {
  6058. int size;
  6059. NodePM p;
  6060.  
  6061.     if((p=bp->freenodes[type][levels]))
  6062.     {
  6063.         bp->freenodes[type][levels] = p->fptr[0];
  6064.         p->value = 0;
  6065.         return p;
  6066.     }
  6067.      size = sizeof(struct _nodeM) + levels * sizeof(void*);
  6068.     p = new_chunk(bp, size, type);
  6069.     p->levels = levels;
  6070.     p->value = 0;
  6071.     return p;    
  6072. }
  6073. static void
  6074. free_Mnode(struct _bins *bp, NodePM p, int type)
  6075. {
  6076.     p->fptr[0] = bp->freenodes[type][p->levels];
  6077.     bp->freenodes[type][p->levels] = p;
  6078. }
  6079. static struct _addr *
  6080. new_addr(struct _bins *bp)
  6081. {
  6082. struct _addr *p;
  6083.     if((p=bp->freeaddrlocs))
  6084.     {
  6085.         bp->freeaddrlocs = p->fptr;
  6086.         return p;
  6087.     }
  6088.     return new_chunk(bp, sizeof(struct _addr), FREEH);
  6089. }
  6090. static void
  6091. free_addr(struct _bins *bp, struct _addr *p)
  6092. {
  6093.     p->fptr = bp->freeaddrlocs;
  6094.     bp->freeaddrlocs = p;
  6095. }
  6096. static struct _bins *
  6097. new_bins(void)
  6098. {
  6099. struct _bins *p;
  6100.     if((p=freebinlocs))
  6101.     {
  6102.         freebinlocs = p->fptr;
  6103.         return p;
  6104.     }
  6105.      if(binsize < sizeof(struct _bins))
  6106.     {
  6107.         binbase = THEWELL(4096);
  6108.         binsize = 4096;
  6109.     }
  6110.     binsize -= sizeof(struct _bins);
  6111.     p = (struct _bins*)binbase;
  6112.     binbase += sizeof(struct _bins);
  6113.     return p;
  6114. }
  6115. static void
  6116. free_bins(struct _bins *p)
  6117. {
  6118.     p->fptr = freebinlocs;
  6119.     freebinlocs = p;
  6120. }
  6121. static int
  6122. getMlevel (struct _bins *p, int binlevel)
  6123. {
  6124. int level = -1;
  6125. int bits = 0;
  6126.  
  6127.     while(bits == 0)
  6128.     {
  6129.         if (p->nbits == 0)
  6130.         {
  6131.             p->bits = lrandom();
  6132.             p->nbits = 15;
  6133.         }
  6134.         bits = p->bits & 3;
  6135.         p->bits >>= 2;
  6136.         p->nbits--;
  6137.  
  6138.         if(++level > binlevel)
  6139.             break;
  6140.     }
  6141.     return (level > MAL_MAXLEVEL) ? MAL_MAXLEVEL : level;
  6142. }
  6143.  
  6144. static void
  6145. init_bins(struct _bins *bp, int category)
  6146. {
  6147. int i;
  6148. int binnum = category % 1009;
  6149.  
  6150.     bzero(bp, sizeof(struct _bins));
  6151.     bp->bincat = category;
  6152.     bp->minloc = 0xffffffff;
  6153.     bp->fptr = hmap[binnum];
  6154.     hmap[binnum] = bp;
  6155.     bp->SIZEHheader = new_Mnode(bp, MAL_MAXLEVEL+1, SIZEH);
  6156.     bp->FREEHheader = new_Mnode(bp, MAL_MAXLEVEL+1, FREEH);
  6157.     bp->USEDHheader = new_Mnode(bp, MAL_MAXLEVEL+1, USEDH);
  6158.  
  6159.     for(i = 0; i <= MAL_MAXLEVEL; ++i)
  6160.     {
  6161.         bp->SIZEHheader->fptr[i] = _NILLL;
  6162.         bp->FREEHheader->fptr[i] = _NILLL;
  6163.         bp->USEDHheader->fptr[i] = _NILLL;
  6164.     }
  6165. }
  6166.  
  6167. static struct _bins*
  6168. getcat(int category)
  6169. {
  6170. struct _bins *hbp;
  6171.  
  6172.     hbp = hmap[category % 1009];
  6173.     while(hbp)
  6174.     {
  6175.         if(hbp->bincat == category)
  6176.             return hbp;
  6177.         hbp = hbp->fptr;
  6178.     }
  6179.     return 0;
  6180. }
  6181. static struct _bins *
  6182. initcat(int category)
  6183. {
  6184. struct _bins *bp;
  6185.  
  6186.     if(category == 0)
  6187.     {
  6188.         bp = &zbp;
  6189.         if(zbp.SIZEHheader == 0)
  6190.             init_bins(bp, category);
  6191.         return bp;
  6192.     }
  6193.     /* do this to set zbp.guarded properly on startup */
  6194.     if(zbp.SIZEHheader == 0)
  6195.         initcat(0);
  6196.  
  6197.     if((bp = new_bins()))
  6198.     {
  6199.         init_bins(bp, category);
  6200.         return bp;
  6201.     }
  6202.     return 0;
  6203. }
  6204. static void *
  6205. getspace(struct _bins *bp, unsigned size, unsigned *remainder)
  6206. {
  6207. unsigned desired;
  6208. void *address;
  6209.   
  6210.     desired = ((size+ALLOCSIZE-1)/ALLOCSIZE)*ALLOCSIZE;
  6211.     if(bp->bincat == 0)
  6212.     {
  6213.         address = THEWELL(desired);
  6214.         *remainder = desired - size;
  6215.     }
  6216.     else
  6217.     {
  6218.     struct _catlocs *cl;
  6219.  
  6220.         if((desired-size) > zbp.guarded)
  6221.             desired -= zbp.guarded;
  6222.         
  6223.         address = Cmalloc(0, desired);
  6224.         *remainder = desired - size;
  6225.  
  6226.         /* save the gross allocations for the category */
  6227.         cl = new_catloc();
  6228.         cl->addr = address;
  6229.         cl->fptr = bp->catlocs;
  6230.         bp->catlocs = cl;
  6231.     }
  6232.     /* maintain address range info */
  6233.     if((unsigned)address < bp->minloc)
  6234.         bp->minloc = (unsigned)address;
  6235.     if(((unsigned)address + desired) > bp->maxloc)
  6236.         bp->maxloc = (unsigned)address + desired;
  6237.      if(bp->minloc < minloc)
  6238.          minloc = bp->minloc;
  6239.      if(bp->maxloc > maxloc)
  6240.          maxloc = bp->maxloc;
  6241.     return address;
  6242. }
  6243. static void
  6244. addto_sizelist(struct _bins *bp, AddrP ap)
  6245. {
  6246. SKIPVARS;
  6247.  
  6248.     /* INSERT IN SIZE LIST */
  6249.     FINDKEY(SIZEH, ap->size)
  6250.  
  6251.     if(node->key == ap->size)
  6252.     {/* size node exists */
  6253.         ap->fptr = (AddrP)node->value;
  6254.         ap->bptr = (AddrP)&node->value;
  6255.         if(ap->fptr) ap->fptr->bptr = ap;
  6256.         node->value = (unsigned)ap;
  6257.     }
  6258.     else
  6259.     {/* create new size node */
  6260.         SETLEVEL(SIZEH)
  6261.         node = new_Mnode(bp, level, SIZEH);
  6262.         node->key = ap->size;
  6263.         node->value = (unsigned)ap;
  6264.         ap->fptr = 0;
  6265.         ap->bptr = (AddrP)&node->value;
  6266.         INSERT()
  6267.     }
  6268. }
  6269. static void
  6270. addto_freelist(struct _bins *bp, void *addr, unsigned size)
  6271. {
  6272. SKIPVARS;
  6273. AddrP ap,sp;
  6274. unsigned dsize[2];
  6275.  
  6276.     /* GET NEW ADDR STRUCT */
  6277.     ap = new_addr(bp);
  6278.     ap->size = size;
  6279.  
  6280.     dsize[1] = dsize[0] = 0; /* sizenode deletion markers */
  6281.  
  6282.     /* CHECK FREE LIST */
  6283.     FINDKEY(FREEH, (unsigned)addr)
  6284.  
  6285.     /* CHECK FOR MERGE OR INSERT */
  6286.     if(prev->value && prev->key+((AddrP)prev->value)->size == (unsigned)addr)
  6287.     {/* merge with previous block */
  6288.         ap->size += ((AddrP)prev->value)->size;
  6289.  
  6290.         if(prev->key + ap->size == node->key)
  6291.         {/* merge with previous and next block */
  6292.             sp = (AddrP) node->value;;
  6293.             ap->size += sp->size;
  6294.  
  6295.             /* delete size struct for next block */
  6296.             UNLINK(sp, 0)
  6297.  
  6298.             /* delete next block */
  6299.             DELETENODE(FREEH);
  6300.         }
  6301.         /* delete size struct for prev block */
  6302.         sp = (AddrP)prev->value;
  6303.         UNLINK(sp, 1)
  6304.  
  6305.         /* set new address struct */
  6306.         prev->value = (unsigned)ap;
  6307.         ap->maddr = prev;
  6308.     }
  6309.     else if(node->value && (char*)addr + size == (void*)node->key)
  6310.     {/* merge with next block */
  6311.         sp = (AddrP) node->value;;
  6312.         node->key = (unsigned)addr;
  6313.         ap->size += sp->size;
  6314.  
  6315.         /* unlink size struct for next block */
  6316.         UNLINK(sp,0)
  6317.  
  6318.         /* set new address struct */
  6319.         node->value = (unsigned)ap;
  6320.         ap->maddr = node;
  6321.     }
  6322.     else
  6323.     {/* insert in free list */
  6324.  
  6325.         SETLEVEL(FREEH)
  6326.         node = new_Mnode(bp, level, FREEH);
  6327.         node->key = (unsigned)addr;
  6328.         node->value = (unsigned)ap;
  6329.         ap->maddr = node;
  6330.         INSERT()
  6331.     }
  6332.     addto_sizelist(bp, ap);
  6333.  
  6334.     /* Remove sizenodes eliminated by merge */
  6335.     if(dsize[0])
  6336.     {
  6337.         FINDKEY(SIZEH, dsize[0])
  6338.         if(node->value == 0)
  6339.           DELETENODE(SIZEH)
  6340.     }
  6341.     if(dsize[1])
  6342.     {
  6343.         FINDKEY(SIZEH, dsize[1])
  6344.         if(node->value == 0)
  6345.           DELETENODE(SIZEH)
  6346.     }
  6347. }
  6348.  
  6349. LOCAL void* 
  6350. Cmemalign(int category, unsigned alignment, unsigned req)
  6351. {
  6352. SKIPVARS;
  6353. NodePM fnode;
  6354. unsigned remainder;
  6355. unsigned *address;
  6356. struct _bins *bp;
  6357. unsigned mask, size;
  6358.  
  6359.  
  6360.     if(!(bp = getcat(category)))
  6361.       if(!(bp = initcat(category)))
  6362.         return 0;
  6363. HEAPCHECK
  6364.     if(req == 0)
  6365.         req = ALIGNMENTM;
  6366.     else
  6367.         req += ROUNDINGM(req);
  6368.     size = req += bp->guarded;
  6369.  
  6370.     if(alignment)
  6371.     {
  6372.         alignment += ROUNDINGM(alignment);
  6373.         if(alignment > ALIGNMENTM)
  6374.         {
  6375.             mask = alignment -1;
  6376.             size = req + alignment + bp->guarded;
  6377.         }
  6378.         else
  6379.         {
  6380.             alignment = 0;
  6381.         }
  6382.     }
  6383.  
  6384.     /* check sizelist for candidate */
  6385.     FINDKEY(SIZEH, size)
  6386.     fnode = node;
  6387. trynext:
  6388.     if(node->key != 0xffffffff)
  6389.     {/* found an appropriately sized block */
  6390.     AddrP sp = (AddrP)node->value;
  6391.  
  6392.         if(!sp && node == fnode)
  6393.         {
  6394.         NodePM q;
  6395.             q = node->fptr[0];
  6396.             DELETENODE(SIZEH)
  6397.             node = q;
  6398.             goto trynext;
  6399.         }
  6400.         if(!sp)
  6401.         {/* no available space at this size */
  6402.             node = node->fptr[0];
  6403.             goto trynext;
  6404.         }
  6405.  
  6406.         /* extract some space from this block */
  6407.         remainder = node->key - size;
  6408.         address = (void*)sp->maddr->key;
  6409.         sp->maddr->key += size;
  6410.         DETACH(sp);
  6411.  
  6412.         if(node->value == 0)
  6413.         {/* no more blocks of this size, delete sizenode */
  6414.             if(node != fnode)
  6415.               FINDKEY(SIZEH, size)
  6416.             DELETENODE(SIZEH)
  6417.         }
  6418.  
  6419.         if(remainder == 0)
  6420.         {/* no remaining space,the node in freelist is exhausted, delete it */
  6421.             FINDKEY(FREEH, sp->maddr->key)
  6422.             DELETENODE(FREEH)
  6423.             free_addr(bp, sp);
  6424.         }
  6425.         else
  6426.         {/* space remains in block, move it to new size loc */
  6427.             sp->size = remainder;
  6428.             addto_sizelist(bp, sp);
  6429.         }
  6430.     }
  6431.     else
  6432.     {
  6433.         address = getspace(bp, size, &remainder);
  6434.         if(remainder)
  6435.           addto_freelist(bp, ((char*)address)+size, remainder);
  6436.     }
  6437.     if(alignment)
  6438.     {
  6439.     unsigned diff;
  6440.         if((diff = (unsigned)address & mask))
  6441.         {/* move address forward */
  6442.         char *naddress;
  6443.         unsigned lose;
  6444.             lose = alignment - diff;
  6445.             naddress = (char*)address + lose;
  6446.             addto_freelist(bp, address, lose);
  6447.             address = (unsigned*)naddress;
  6448.         }
  6449.     }
  6450.     if(bp->guarded)
  6451.     {
  6452.       *address = FRNTGUARD;
  6453.       *((unsigned*)(((char*)address)+req-ALIGNMENTM)) = BACKGUARD;
  6454.  
  6455.     }
  6456.  
  6457.     FINDKEY(USEDH, (unsigned)address)
  6458.  
  6459.     if(node->key == (unsigned)address) {
  6460.       PERROR(pName ":ERROR:allocC:%d: bookkeeping nodes corrupted at:0x%x\n",
  6461.           category, address);
  6462.     }
  6463.     SETLEVEL(USEDH)
  6464.     node = new_Mnode(bp, level, USEDH);
  6465.     node->key = (unsigned)address;
  6466.     node->value = req;
  6467.     INSERT()    
  6468.  
  6469.     return address+bp->addrbump;
  6470. }
  6471. LOCAL void*
  6472. Ccalloc(int category, unsigned cnt, unsigned elem_size)
  6473. {
  6474. unsigned size = cnt * elem_size;
  6475. void* buf;;
  6476.  
  6477.   if((buf = Cmalloc(category, size)))
  6478.       bzero(buf, size);
  6479.   return buf;
  6480. };
  6481. LOCAL void
  6482. Cfree(int category, void* addr)
  6483. {
  6484. unsigned cursize;
  6485. unsigned *address;
  6486. struct _bins *bp;
  6487. SKIPVARS;
  6488.     if(addr)
  6489.     {
  6490.         if(!(bp = getcat(category))) {
  6491.             PERROR(pName ":ERROR:Cfree:%d: non-existant category at:0x%x\n",category,addr);
  6492.         }
  6493. HEAPCHECK
  6494.         address = (void*) ((unsigned*)addr - bp->addrbump);
  6495.         FINDKEY(USEDH, (unsigned)address)
  6496.         if(node->key != (unsigned)address) {
  6497.           PERROR(pName ":ERROR:Cfree:%d: bogus address=0x%x\n", category, addr);
  6498.         }
  6499.         cursize = node->value;
  6500.         CHECKGUARDS(Cfree)
  6501.         DELETENODE(USEDH)
  6502.  
  6503.         addto_freelist(bp, address, cursize);
  6504.     }
  6505.     else PERROR(pName ":ERROR:Cfree:%d: null pointer\n", category);
  6506. }
  6507. LOCAL void* 
  6508. Crealloc(int category, void* addr, unsigned newsize)
  6509. {
  6510. SKIPVARS;
  6511. unsigned cursize;
  6512. unsigned *address;
  6513. struct _bins *bp;
  6514. NodePM onode;
  6515.  
  6516.     if(addr == 0) 
  6517.         return Cmalloc(category, newsize);
  6518.     else
  6519.     {
  6520.         if(!(bp = getcat(category))) {
  6521.            PERROR(pName ":ERROR:reallocC:%d: non-existant category at:%x\n",category,addr);
  6522.         }
  6523. HEAPCHECK 
  6524.         if(newsize == 0)
  6525.             newsize = ALIGNMENTM;
  6526.         else
  6527.             newsize += ROUNDINGM(newsize);
  6528.         newsize += bp->guarded;
  6529.  
  6530.         address = (void*)(((char*)addr)-(bp->guarded/2));
  6531.         FINDKEY(USEDH, (unsigned)address)
  6532.         if(node->key != (unsigned)address) {
  6533.           PERROR(pName ":ERROR:reallocC:%d: bogus address=0x%x\n", category, addr);
  6534.         }
  6535.         cursize = node->value;
  6536.         node->value = newsize;
  6537.         onode = node;
  6538.  
  6539.         CHECKGUARDS(reallocC)
  6540.  
  6541.         if(newsize == cursize)
  6542.             return addr;
  6543.         if(newsize > cursize)
  6544.         {/* check if block can be extended */
  6545.         void *taddr = ((char*)address) + cursize;
  6546.         unsigned extendsize = newsize-cursize;
  6547.  
  6548.             /* check freelist for an available block at the right address */
  6549.             FINDKEY(FREEH, (unsigned)taddr)
  6550.             if(node->key == (unsigned)taddr)
  6551.             {
  6552.             AddrP sp = (AddrP)node->value;
  6553.                 if(sp->size >= extendsize)
  6554.                 {/* BLOCK CAN BE EXTENDED INTERNALLY */
  6555.                     node->key += extendsize;
  6556.                     sp->size -= extendsize;
  6557.                     DETACH(sp)
  6558.                     if(sp->size == 0)
  6559.                     {/* the extension block is used up, delete this node */
  6560.                         free_addr(bp, sp);
  6561.                         DELETENODE(FREEH)
  6562.                     }
  6563.                     else
  6564.                     {/* shift the remainder in the sizelist */
  6565.                         addto_sizelist(bp, sp);
  6566.                     }
  6567.                     /* SUCCESS */
  6568.                     if(bp->guarded)
  6569.                     {
  6570.                         *((unsigned*)(((char*)address)+newsize-ALIGNMENTM))
  6571.                             = BACKGUARD;
  6572.                     }
  6573.                     return addr;
  6574.                 }
  6575.             }
  6576.             /* HERE WE COULD CHECK OTHER SOURCES OF SPACE */
  6577.  
  6578.             /* can't extend block, malloc some new space */
  6579.             if((taddr = Cmalloc(category,newsize-bp->guarded)))
  6580.             {
  6581.                 memmove(taddr,addr,cursize-bp->guarded);
  6582.                 onode->value = cursize;
  6583.                 Cfree(category, addr);
  6584.             }
  6585.             /* SUCCESS */
  6586.             return taddr;
  6587.         }
  6588.         else
  6589.         {/* shrink block */
  6590.             if(bp->guarded)
  6591.             {
  6592.                 *((unsigned*)(((char*)address)+newsize-ALIGNMENTM))
  6593.                     = BACKGUARD;
  6594.             }
  6595.             addto_freelist(bp, ((char*)address)+newsize, cursize-newsize); 
  6596.             return addr;
  6597.         }
  6598.       }
  6599. }
  6600. LOCAL void
  6601. Cfreecat(int category)
  6602. {
  6603. struct _bins *bp;
  6604.  
  6605.     if(category == 0)
  6606.         return;
  6607.  
  6608.     if((bp = getcat(category)))
  6609.     {
  6610.     struct _catlocs *cl = bp->catlocs;
  6611.     struct _bins *hbp;
  6612.     struct _bins *prev;
  6613.  
  6614.         while(cl)
  6615.         {/* Space allocated to the category is moved to category 0 */
  6616.         void *ql = cl->fptr;
  6617.  
  6618.             Cfree(0, cl->addr);
  6619.             free_catloc(cl);
  6620.             cl = ql;
  6621.         }
  6622.         /* space for the _bins struct is placed on a free list */
  6623.         hbp = hmap[category % 1009];
  6624.         prev = 0;
  6625.         while(hbp)
  6626.         {
  6627.             if(hbp->bincat == category)
  6628.             {
  6629.                 if(prev == 0)
  6630.                     hmap[category % 1009] = hbp->fptr;
  6631.                 else
  6632.                     prev->fptr = hbp->fptr;
  6633.                 free_bins(hbp);
  6634.                 return;
  6635.             }
  6636.             prev = hbp;
  6637.             hbp = hbp->fptr;
  6638.         }
  6639.     }
  6640. }
  6641. LOCAL int
  6642. Cmemrange(int category, unsigned *min, unsigned *max)
  6643. {
  6644. struct _bins *bp;
  6645.  
  6646.     if((bp = getcat(category)))
  6647.     {
  6648.         *min = bp->minloc;
  6649.         *max = bp->maxloc;
  6650.         return 1;
  6651.     }
  6652.     return 0;
  6653. }
  6654. LOCAL int
  6655. Cusedrange(int category, unsigned *min, unsigned *max)
  6656. {
  6657. struct _bins *bp;
  6658. NodePM node;
  6659. int level;
  6660.  
  6661.     if((bp = getcat(category)))
  6662.     {
  6663.         node = bp->USEDHheader;
  6664.         *min = node->fptr[0]->key;
  6665.         for(level = bp->USEDHlevel; level >= 0; level--)
  6666.           while(node->fptr[level]->key < 0xffffffff)
  6667.             node = node->fptr[level];
  6668.         *max = node->key;
  6669.         return 1;
  6670.     }
  6671.     return 0;
  6672. }
  6673. LOCAL void
  6674. Ctotrange(unsigned *min, unsigned *max)
  6675. {
  6676.     *min = minloc;
  6677.     *max = maxloc;
  6678. }
  6679. LOCAL void
  6680. Cguard(int category)
  6681. {
  6682. struct _bins *bp;
  6683.  
  6684.     if(!(bp = getcat(category)))
  6685.       if(!(bp = initcat(category)))
  6686.           return;
  6687.  
  6688.     if(!bp->guarded)
  6689.     {
  6690.         bp->guarded = 2*ALIGNMENTM;
  6691.         bp->addrbump = 1;
  6692.     }
  6693. }
  6694. LOCAL void*
  6695. Cheapcheck(int category, void *start)
  6696. {
  6697. struct _bins *bp;
  6698. NodePM node,prev;
  6699. unsigned *p1,*p2;
  6700.  
  6701.     if((bp = getcat(category)))
  6702.     {
  6703.         if(bp->guarded)
  6704.         {
  6705.             prev = 0;
  6706.             node = bp->USEDHheader;
  6707.             while(        (node = node->fptr[0]) != (NodePM)0xffffffff
  6708.                     &&    node->key != 0xffffffffUL)
  6709.             {
  6710.                 if((void*)node->key > start)
  6711.                 {
  6712.                     p1 = (unsigned*)node->key;
  6713.                     if(*p1 != FRNTGUARD)
  6714.                     {
  6715.                         if(prev)
  6716.                             return (char*)prev->key+ALIGNMENTM;
  6717.                         else
  6718.                             return (void*)1;
  6719.                     }
  6720.                     p2 = (unsigned*)(((char*)p1)+node->value-ALIGNMENTM);
  6721.                     if(*p2 != BACKGUARD)
  6722.                         return (char*)node->key+ALIGNMENTM;
  6723.                 }
  6724.                 prev = node;
  6725.             }
  6726.         }
  6727.     }
  6728.     return 0;
  6729. }
  6730. LOCAL void* 
  6731. Cmalloc(int category, unsigned size)
  6732. {
  6733.     return Cmemalign(category, 0, size);
  6734. }
  6735.  
  6736. LOCAL void* 
  6737. Cvalloc(int category, unsigned bytes)
  6738. {
  6739.   return Cmemalign (category, PAGESIZE, bytes);
  6740. }
  6741. LOCAL unsigned
  6742. Cmallocsize(int category, void* addr)
  6743. {
  6744. struct _bins *bp;
  6745. SKIPVARS;
  6746.  
  6747.     if(addr && (bp = getcat(category)))
  6748.     {
  6749.     unsigned address = (unsigned)((unsigned*)addr - bp->addrbump);
  6750.         FINDKEY(USEDH, address)
  6751.         if(node->key == address)
  6752.             return node->value - bp->guarded;
  6753.     }
  6754.     return 0;
  6755. }
  6756.  
  6757. LOCAL int
  6758. Cnewcat()
  6759. {
  6760. static unsigned int cat = BASE_CATEGORY;
  6761.     return ++cat;
  6762. }
  6763. /* ====================== END MULTI-HEAP MALLOC ============================ */
  6764.  
  6765.  
  6766. /* ====================== SYMBOL TABLE HANDLERS ============================ */
  6767.  
  6768. typedef struct _key
  6769. {
  6770.     unsigned long k[2];
  6771.     unsigned long hv;
  6772. } KEY, *KEYP;
  6773.  
  6774. typedef struct _nodeS
  6775. {/* 40 bytes -- adjust size to suit application */
  6776.     unsigned long value[4];    /* 16 bytes */
  6777.     unsigned long key[2];    /* 8 bytes */
  6778.     struct _nodeS *fptr[4];    /* 16 bytes */
  6779. } NodeS, *NodePS;
  6780.  
  6781. typedef struct _pbuf
  6782. {/* symbol table object */
  6783.     int    nbins;            /* number of bins in dictionary */
  6784.     int lastbin;        /* for seq access */
  6785.     NodePS lastptr;        /* ditto */
  6786.     int category;        /* heap number */
  6787.     char *chunkbase;    /* node allocation base */
  6788.     int chunksize;        /* number of bytes available in current chunk */
  6789.     NodePS freelist;    /* list of freed nodes for allocation */
  6790.     int level;            /* sorted level */
  6791.     int bits;            /* sorted bits */
  6792.     int bitcnt;            /* sorted bitcnt */
  6793.     NodePS header;        /* sorted header */
  6794.     NodePS bins[0];        /* bins if hashed dictionary */
  6795. } *PbufP;
  6796.  
  6797. #define SYM_MAXLEVEL 12
  6798. #define TBL ((PbufP)tbl)
  6799.  
  6800. static struct _nodeS _nnil = {{0,0,0,0},{0xffffffff,0xffffffff},{0,0,0,0}};
  6801. static struct _nodeS *_NNIL = &_nnil;
  6802.  
  6803. static int
  6804. getSlevel (PbufP tbl)
  6805. {
  6806. int level = -1;
  6807. int bits = 0;
  6808.  
  6809.     while (bits == 0)
  6810.     {
  6811.         if (tbl->bitcnt == 0)
  6812.         {
  6813.             tbl->bits = lrandom();
  6814.             tbl->bitcnt = 15;
  6815.         }
  6816.  
  6817.         bits = tbl->bits & 3;
  6818.         tbl->bits >>= 2;
  6819.         tbl->bitcnt--;
  6820.  
  6821.         if(++level > tbl->level)
  6822.             break;
  6823.     }
  6824.     return (level > SYM_MAXLEVEL) ? SYM_MAXLEVEL : level;
  6825.  
  6826. }
  6827.  
  6828. static void
  6829. hash(void *key, KEY *cat)
  6830. {
  6831.     cat->k[0] = ((unsigned long*)key)[0];
  6832.     cat->k[1] = ((unsigned long*)key)[1];
  6833.     cat->hv = ((cat->k[0] ^ cat->k[1]) * 1103515245UL) + 12345;
  6834. }
  6835. static void
  6836. sym_hash(unsigned long *key, char *symb)
  6837. {
  6838. int len = strlen(symb);
  6839. int i;
  6840.     for(i = 0; i < len; ++i)
  6841.       ((unsigned char *)key)[i & 7] ^= symb[i];
  6842.     key[0] = ((key[0] ^ key[1]) * 1103515245UL) + 12345;
  6843.     key[1] = len;
  6844. }
  6845. static void *
  6846. new_Snode(PbufP tbl, int levels)
  6847. {
  6848. NodePS p;
  6849. int size;
  6850.     if(levels <= 3)
  6851.     {
  6852.         if(tbl->freelist)
  6853.         {
  6854.             p = tbl->freelist;
  6855.             tbl->freelist = p->fptr[0];
  6856.             p->fptr[0] = 0;
  6857.             return p;
  6858.         }
  6859.     }
  6860.     size = sizeof(struct _nodeS) + ((levels-3) * sizeof(void*));
  6861.     if(tbl->chunksize < size)
  6862.     {
  6863.         tbl->chunkbase = Ccalloc(tbl->category, 1, 4080);
  6864.         tbl->chunksize = 4080;
  6865.     } 
  6866.     tbl->chunksize -= size;
  6867.     p = (NodePS)tbl->chunkbase;
  6868.     tbl->chunkbase += size;
  6869.     return p;
  6870. }
  6871. static void
  6872. free_Snode(PbufP tbl, NodePS node)
  6873. {
  6874.     bzero(node, sizeof(struct _nodeS));
  6875.     node->fptr[0] = tbl->freelist;
  6876.     tbl->freelist = node;
  6877. }
  6878.  
  6879. static void*
  6880. NewSymTable(int category, int nbins)
  6881. {
  6882. PbufP tbl;
  6883.  
  6884.     tbl = Ccalloc(category, 1, nbins*sizeof(NodePS) + sizeof(struct _pbuf));
  6885.     if(nbins == 0)
  6886.     {/* sorted dictionary */
  6887.     int i;
  6888.         tbl->header = new_Snode(tbl, SYM_MAXLEVEL+1);
  6889.         for(i = 0; i <= SYM_MAXLEVEL; ++i)
  6890.             tbl->header->fptr[i] = _NNIL;
  6891.     }
  6892.     tbl->nbins = nbins;
  6893.     tbl->category = category;
  6894.     return tbl;
  6895. }
  6896. static int
  6897. SymFind(void *tbl, void *key, void *result)
  6898. {
  6899. NodePS node;
  6900.  
  6901.     if(tbl && key)
  6902.     {
  6903.       if(TBL->nbins)
  6904.       {/* hashed dictionary */
  6905.       KEY cat;
  6906.  
  6907.         hash(key, &cat);
  6908.         if((node = TBL->bins[cat.hv % TBL->nbins]))
  6909.         {
  6910.             do {
  6911.                 if(        node->key[0] == cat.k[0]
  6912.                     &&    node->key[1] == cat.k[1])
  6913.                 {
  6914.                     if(result)
  6915.                       *((NodePS *)result) = node;
  6916.                     TBL->lastbin = cat.hv % TBL->nbins;
  6917.                     TBL->lastptr = node;
  6918.                     return 1;
  6919.                 }
  6920.              } while((node = node->fptr[0]));
  6921.         }
  6922.         return 0;
  6923.       }
  6924.       else
  6925.       {/* sorted dictionary */
  6926.       int level;
  6927.  
  6928.         node = TBL->header;
  6929.         for(level = TBL->level; level >= 0; level--)
  6930.         {
  6931.           while( KEYLT(node->fptr[level]->key, ((unsigned long*)key)) )
  6932.             node = node->fptr[level];
  6933.         }
  6934.         node = node->fptr[0];
  6935.  
  6936.         TBL->lastptr = node;
  6937.         if(result)
  6938.             *((NodePS *)result) = node;
  6939.         return (KEYEQ(node->key, ((unsigned long*)key))) ? 1 : 0;
  6940.       }
  6941.     }
  6942.     return 0;
  6943. }
  6944. static int
  6945. SymFindRange(void *tbl, void *key, void *result)
  6946. {/* assumes 4 byte key and value (the value can be bigger) */
  6947. NodePS node;
  6948.  
  6949.     if(tbl && key)
  6950.     {
  6951.       if(TBL->nbins)
  6952.       {/* hashed dictionary */
  6953.         return 0;
  6954.       }
  6955.       else
  6956.       {/* sorted dictionary */
  6957.       NodePS prev;
  6958.       int level;
  6959.  
  6960.         node = TBL->header;
  6961.         for(level = TBL->level; level >= 0; level--)
  6962.         {
  6963.           while ( node->fptr[level]->key[0] < ((unsigned long*)key)[0] )
  6964.             node = node->fptr[level];
  6965.         }
  6966.         prev = node;
  6967.         node = node->fptr[0];
  6968.  
  6969.         if( node->key[0] == ((unsigned long*)key)[0] )
  6970.         {
  6971.             TBL->lastptr = node;
  6972.             if(result)
  6973.                 *((NodePS *)result) = node;
  6974.             return 1;
  6975.         }        
  6976.         if( ((unsigned long*)key)[0] < prev->key[0]+prev->value[0] )
  6977.         {
  6978.             TBL->lastptr = prev;
  6979.             if(result)
  6980.                 *((NodePS *)result) = prev;
  6981.             return 1;
  6982.         }
  6983.         return 0;
  6984.       }
  6985.     }
  6986.     return 0;
  6987. }
  6988. static void *
  6989. SymInsert(void *tbl, void *key, void *value, int datsiz)
  6990. {
  6991. NodePS node;
  6992.  
  6993.     if(tbl && key)
  6994.     {
  6995.       if(TBL->nbins)
  6996.       {/* hashed dictionary */
  6997.       KEY cat;
  6998.       NodePS *binp;
  6999.         hash(key, &cat);
  7000.         node = new_Snode(tbl, 0);
  7001.         TBL->lastbin = cat.hv % TBL->nbins;
  7002.         TBL->lastptr = node;
  7003.         binp = &TBL->bins[TBL->lastbin];
  7004.         if(value && datsiz)
  7005.           memcpy(node, value, MIN(datsiz,16));
  7006.         node->key[0] = cat.k[0];
  7007.         node->key[1] = cat.k[1];
  7008.         node->fptr[0] = *binp;
  7009.         *binp = node;
  7010.         return node;
  7011.       }
  7012.       else
  7013.       {/* sorted dictionary */
  7014.       int level;
  7015.       NodePS update[SYM_MAXLEVEL+1];
  7016.  
  7017.         node = TBL->header;
  7018.         for (level = TBL->level; level >= 0; level--)
  7019.         {
  7020.           while ( KEYLT(node->fptr[level]->key,((unsigned long*)key)) )
  7021.             node = node->fptr[level];
  7022.           update[level] = node;
  7023.         }
  7024.  
  7025.         level = getSlevel(tbl);
  7026.  
  7027.         while(TBL->level < level)
  7028.             update[++TBL->level] = TBL->header;
  7029.  
  7030.         node = new_Snode(tbl, level);
  7031.  
  7032.         if(value && datsiz)
  7033.           memcpy(node, value, MIN(datsiz,16));
  7034.         node->key[0] = ((unsigned long*)key)[0];
  7035.         node->key[1] = ((unsigned long*)key)[1];
  7036.  
  7037.         while(level >= 0)
  7038.         {
  7039.             node->fptr[level] = update[level]->fptr[level];
  7040.             update[level]->fptr[level] = node;
  7041.             level--;
  7042.         }
  7043.         TBL->lastptr = node;
  7044.         return node;
  7045.      }
  7046.     }
  7047.     return 0;
  7048. }
  7049. static int
  7050. StringFind(void *tbl, char *string, void *result)
  7051. {
  7052. unsigned long key[2];
  7053. struct {
  7054.     char *symname;
  7055. } *valp;
  7056.  
  7057.     key[0] = 0;
  7058.     key[1] = 0;
  7059.     sym_hash(key, string);
  7060.  
  7061.     if(SymFind(tbl, key, &valp))
  7062.     {
  7063.     unsigned long *key1;
  7064.         do {
  7065.             if(!strcmp(string, valp->symname))
  7066.             {
  7067.                 if(result)
  7068.                     *((void**)result) = valp;
  7069.                 return 1;
  7070.             }
  7071.             /* Check duplicates */
  7072.             if(!SymNext(tbl))
  7073.                 break;
  7074.             SymKey(tbl, &key1);
  7075.             SymValue(tbl, &valp);
  7076.         } while(KEYEQ(key, key1));
  7077.     }
  7078.     return 0;
  7079. }
  7080. static int
  7081. StringInsert(void *tbl, char *string, void *result)
  7082. {
  7083. unsigned long key[2];
  7084. struct {
  7085.     char *symname;
  7086. } *valp;
  7087.  
  7088.     key[0] = 0;
  7089.     key[1] = 0;
  7090.     sym_hash(key, string);
  7091.     if(SymFind(tbl, key, &valp))
  7092.     {/* hash keys match */
  7093.     unsigned long *key1;
  7094.         do {
  7095.             if(!strcmp(string, valp->symname))
  7096.             {
  7097.                 if(result)
  7098.                     *((void**)result) = valp;
  7099.                 return 1;
  7100.             }
  7101.             /* Check duplicates */
  7102.             if(!SymNext(tbl))
  7103.                 break;
  7104.             SymKey(tbl, &key1);
  7105.             SymValue(tbl, &valp);
  7106.         } while(KEYEQ(key, key1));
  7107.     }
  7108.     /* NOMATCH */
  7109.     valp = SymInsert(tbl, key, &string, 4);
  7110.     if(result)
  7111.         *((void**)result) = valp;
  7112.     return 0;
  7113. }
  7114. static void
  7115. SymDelete(void *tbl, void *key)
  7116. {
  7117. NodePS node;
  7118.  
  7119.     if(tbl && key)
  7120.     {
  7121.       if(TBL->nbins)
  7122.       {/* hashed dictionary */
  7123.       KEY cat;
  7124.       NodePS *binp;
  7125.       NodePS prev = 0;
  7126.  
  7127.         hash(key, &cat);
  7128.         binp = &TBL->bins[cat.hv % TBL->nbins];
  7129.         if((node = *binp))
  7130.         {
  7131.             do {
  7132.                 if(        node->key[0] == cat.k[0]
  7133.                     &&    node->key[0] == cat.k[1])
  7134.                 {
  7135.                     if(prev)
  7136.                         prev->fptr[0] = node->fptr[0];
  7137.                     else
  7138.                         *binp = node->fptr[0];
  7139.  
  7140.                     free_Snode(tbl, node);
  7141.                     if(TBL->lastptr == node)
  7142.                     {
  7143.                         TBL->lastptr = 0;
  7144.                         TBL->lastbin = TBL->nbins;
  7145.                     }
  7146.                     return;
  7147.                 }
  7148.                 prev = node;
  7149.              } while((node = node->fptr[0]));
  7150.         }
  7151.       }
  7152.       else
  7153.       {/* sorted dictionary */
  7154.       int level;
  7155.       NodePS update[SYM_MAXLEVEL+1];
  7156.  
  7157.         node = TBL->header;
  7158.         for(level = TBL->level; level >= 0; level--)
  7159.         {
  7160.           while ( KEYLT(node->fptr[level]->key, ((unsigned long*)key)) )
  7161.             node = node->fptr[level];
  7162.           update[level] = node;
  7163.         }
  7164.         node = node->fptr[0];
  7165.  
  7166.         if( KEYEQ(node->key, ((unsigned long*)key)) )
  7167.         {
  7168.             for(level = 0; level <= TBL->level; level++)
  7169.             {
  7170.                 if (update[level]->fptr[level] == node)
  7171.                      update[level]->fptr[level] = node->fptr[level];
  7172.                 else break;
  7173.             }
  7174.  
  7175.             while((TBL->level > 0) && (TBL->header->fptr[TBL->level] == _NNIL))
  7176.                 TBL->level--;
  7177.  
  7178.             if(TBL->lastptr == node)
  7179.                 TBL->lastptr = 0;
  7180.             free_Snode(tbl, node);
  7181.         }
  7182.       }
  7183.     }
  7184. }
  7185. static int
  7186. SymHead(void *tbl)
  7187. {/* Set up for sequential access */
  7188. int nbins;
  7189.  
  7190.     if(tbl)
  7191.     {
  7192.       if((nbins = TBL->nbins))
  7193.       {/* hashed dictionary */
  7194.       NodePS node;
  7195.       int i;
  7196.         TBL->lastptr = 0;
  7197.         for(i = 0; i < nbins; ++i)
  7198.         {
  7199.             if( (node = TBL->bins[i]) != 0)
  7200.             {
  7201.                 TBL->lastbin = i;
  7202.                 return 1;
  7203.             }
  7204.         }
  7205.         TBL->lastbin = nbins;
  7206.         return 0; /* empty */
  7207.       }
  7208.       else
  7209.       {/* sorted dictionary */
  7210.         TBL->lastptr = TBL->header;
  7211.         return (TBL->lastptr->fptr[0] == _NNIL) ? 0 : 1;
  7212.       }
  7213.     }
  7214.     return 0;
  7215. }
  7216. static int
  7217. SymNext(void *tbl)
  7218. {/* Move to next sequential entry */
  7219. int nbins;
  7220.  
  7221.     if(tbl)
  7222.     {
  7223.       if((nbins = TBL->nbins))
  7224.       {/* hashed dictionary */
  7225.         if(TBL->lastptr && ((TBL->lastptr = TBL->lastptr->fptr[0])))
  7226.             return 1;
  7227.         else
  7228.         {
  7229.         int i;
  7230.             for(i = TBL->lastbin; i < nbins; ++i)
  7231.             {
  7232.                 if((TBL->lastptr = TBL->bins[i]) != 0)
  7233.                 {
  7234.                     TBL->lastbin = i+1;
  7235.                     return 1;
  7236.                 }
  7237.             }
  7238.             return 0;
  7239.         }
  7240.       }
  7241.       else
  7242.       {/* sorted dictionary */
  7243.         if(TBL->lastptr)
  7244.         {
  7245.             if(TBL->lastptr != _NNIL)
  7246.                 TBL->lastptr = TBL->lastptr->fptr[0];
  7247.             return (TBL->lastptr == _NNIL) ? 0 : 1;
  7248.         }
  7249.       }
  7250.     }
  7251.     return 0;
  7252. }
  7253. static void
  7254. SymGetMark(void *tbl, void *markptr)
  7255. {
  7256.     if(tbl && markptr)
  7257.     {
  7258.         ((long*)markptr)[0] = TBL->lastbin;
  7259.         ((long*)markptr)[1] = (long)TBL->lastptr;
  7260.     }
  7261. }
  7262. static int
  7263. SymMarkNext(void *tbl, void *mark)
  7264. {/* Mark current position, and move to next sequential entry */
  7265.     SymGetMark(tbl, mark);
  7266.     return SymNext(tbl);
  7267. }
  7268. static void
  7269. SymSetMark(void *tbl, void *markptr)
  7270. {
  7271.     if(tbl && markptr)
  7272.     {
  7273.         TBL->lastbin = ((long*)markptr)[0];
  7274.         TBL->lastptr = (NodePS)((long*)markptr)[1];
  7275.     }
  7276. }
  7277. static void
  7278. SymKey(void *tbl, void *keyptr)
  7279. {/* Retrieve key info pointer for current spot */
  7280.  
  7281.     if(tbl && keyptr && TBL->lastptr)
  7282.         *((unsigned long**)keyptr) = &TBL->lastptr->key[0];
  7283. }
  7284. static void
  7285. SymValue(void *tbl, void *datptr)
  7286. {/* Retrieve value pointer for current spot */
  7287.  
  7288.     if(tbl && datptr && TBL->lastptr)
  7289.         *((unsigned long**)datptr) = &TBL->lastptr->value[0];
  7290. }
  7291.  
  7292. /* ==================== END SYMBOL TABLE HANDLERS ========================== */
  7293.  
  7294. /* ========================== OPTIMIZATION ================================= */
  7295. static int
  7296. forward(unsigned char *p)
  7297. {
  7298. unsigned char *next;
  7299.  
  7300.     do {
  7301.         next = (void*)((Pop)p)->next;
  7302.         while(        *next == 0
  7303.                 ||    *next == lineop
  7304.                 ||    *next == labelop)
  7305.             next = (void*)((Pop)next)->next;
  7306.  
  7307.         if(*next == endop)
  7308.         {
  7309.             if(*p == *(next+8))
  7310.             {
  7311.                 *p = 0;
  7312.                 *next = 0;
  7313.                 return 1;
  7314.             }
  7315.             return 0;
  7316.         }
  7317.     } while(forward(next));
  7318.  
  7319.     return 0;
  7320. }
  7321. static void
  7322. eliminate_extraneous_infops(Piv iv, int level)
  7323. {
  7324. Pafile pf;
  7325. unsigned char *p;
  7326. int i;
  7327.     for(i = 0; i < iv->numfiles; ++i)
  7328.     {
  7329.         iv->filenum = i;
  7330.         pf = iv->files[i];
  7331.         if(!(p = pf->prog_p))
  7332.             continue;
  7333.         if(pf->header_p->hdr.opt_level >= level)
  7334.             continue;
  7335.         pf->header_p->hdr.opt_level = level;
  7336.         while(*p != endfileop)
  7337.         {
  7338.             switch(*p)
  7339.             {
  7340.                 case    unopop:
  7341.                 case    arrayelemop:
  7342.                 case    ptrelemop:
  7343.                 case    strelemop:
  7344.                 case    ptrdimsop:
  7345.                 case    arraydimsop:
  7346.                     forward(p);
  7347.                     break;
  7348.             }
  7349.             p = POP->next;
  7350.         }
  7351.     }
  7352. }
  7353. static void
  7354. clean_temps(Piv iv)
  7355. {
  7356. long *key;
  7357. long *val;
  7358. long hitemp = iv->first_temp & 0xffff0000;
  7359.  
  7360.     if(iv->temps_written == 0)
  7361.         return;
  7362.  
  7363.     if(SymHead(iv->tmptbl))
  7364.     {
  7365.         while(SymNext(iv->tmptbl))
  7366.         {
  7367.             SymKey(iv->tmptbl, &key);
  7368.  
  7369.             if((key[0] & 0xffff0000) == hitemp)
  7370.             {
  7371.             char *ptr;
  7372.             long saveit;
  7373.  
  7374.                 SymValue(iv->tmptbl, &val);
  7375.                 saveit = val[1];
  7376.                 ptr = (void*)val[0];
  7377.                 val[0] = 0;    /* allow reuse of this slot */
  7378.                 val[1] = 0;
  7379.  
  7380.                 while(ptr)
  7381.                 {
  7382.                 void *nptr = (void*)((PopT)ptr)->tmpnum;
  7383.                     ((PopT)ptr)->tmpnum = key[0];
  7384.  
  7385.                     if(!saveit)
  7386.                     {
  7387.                     unsigned char *p = ptr-8;                    
  7388.                     unsigned char op = *p;
  7389.  
  7390.                         *p = 0;                        
  7391.                         ++iv->killop;
  7392.                         if(op == duptmpop)
  7393.                         {/* special test for post increment */
  7394.                             p = POP->next;
  7395.                             p = POP->next;
  7396.                             if(*p == grabop)
  7397.                                 *p = 0;
  7398.                         }
  7399.                     }
  7400.                     ptr = nptr;
  7401.                 }
  7402.             }
  7403.         }
  7404.         if(!hitemp)
  7405.             iv->temps_written = 0;
  7406.     }
  7407. }
  7408.  
  7409. static void
  7410. read_temp(Piv iv, PopT ptr, unsigned long last)
  7411. {
  7412. unsigned long key[2];
  7413. long *result;
  7414.  
  7415.     if(last == ptr->tmpnum)
  7416.         return;
  7417.  
  7418.     key[0] = ptr->tmpnum;
  7419.     key[1] = 0;
  7420.  
  7421.     if(SymFind(iv->tmptbl, key, &result))
  7422.     {
  7423.         result[1] = 1;
  7424.     }
  7425.     else PERROR(pName ":SYSERROR: read temp %d not found\n", key[0]);
  7426. }
  7427. static int 
  7428. reading_self(unsigned char *p, long tmpnum)
  7429. {
  7430.     if((p[2]&0xe0) == OPTEMP || (p[2]&0xe0) == OPRET)
  7431.     {
  7432.           return 1;
  7433.     }
  7434.     if((p[3]&0xe0) == OPTEMP || (p[3]&0xe0) == OPRET)
  7435.     {
  7436.         return 1;
  7437.     }
  7438.     return 0;
  7439. }
  7440. static long
  7441. write_temp(Piv iv, PopT ptr, unsigned char opcode)
  7442. {
  7443. long key[2];
  7444. long val[2];
  7445. long *result;
  7446. long hitemp = ptr->tmpnum & 0xffff0000;
  7447.  
  7448.     if(ptr->atype & A_MEMADDR && opcode < duptmpop)
  7449.     {/* actually reading from this destination slot */
  7450.         read_temp(iv, ptr, 0);
  7451.         return 0;
  7452.     }
  7453.  
  7454.     if(hitemp > (iv->first_temp & 0xffff0000))
  7455.     {/* Inner block, CompoundExp or NestedFunc */
  7456.         iv->first_temp = hitemp + 1;
  7457.     }
  7458.     else if(hitemp < (iv->first_temp & 0xffff0000))
  7459.     {/* Exit inner block */
  7460.         if(!reading_self(((char*)ptr)-8, ptr->tmpnum))
  7461.         {
  7462.             while(hitemp < (iv->first_temp & 0xffff0000))
  7463.             {
  7464.                 clean_temps(iv);
  7465.                 iv->first_temp -= 0x00010000;
  7466.             }
  7467.         }
  7468.     }
  7469.     if(ptr->tmpnum == iv->first_temp)
  7470.     {
  7471.         if(!reading_self(((char*)ptr)-8, ptr->tmpnum))
  7472.             clean_temps(iv);
  7473.     }
  7474.     ++iv->temps_written;
  7475.     key[0] = ptr->tmpnum;
  7476.     key[1] = 0;
  7477.  
  7478.     if(SymFind(iv->tmptbl, key, &result))
  7479.     {
  7480.     PopT optr = (PopT)result[0];
  7481.         result[0] = (long)ptr;
  7482.         ptr->tmpnum = (long)optr;
  7483.     }
  7484.     else
  7485.     {
  7486.         val[0] = (long)ptr;
  7487.         val[1] = 0;
  7488.  
  7489.         SymInsert(iv->tmptbl, key, val, 8);
  7490.         ptr->tmpnum = 0;
  7491.     }
  7492.     return key[0];
  7493. }
  7494. static void
  7495. eliminate_unused_temps(Piv iv, int level)
  7496. {
  7497. Pafile pf;
  7498. unsigned char *p;
  7499. int i;
  7500. long last_write;
  7501.  
  7502.     iv->tmptbl = NewSymTable(iv->category, 111);
  7503.     for(i = 0; i < iv->numfiles; ++i)
  7504.     {
  7505.         iv->filenum = i;
  7506.         pf = iv->files[i];
  7507.         if(pf->header_p->hdr.opt_level >= level)
  7508.             continue;
  7509.         pf->header_p->hdr.opt_level = level;
  7510. rekill:
  7511.         if(!(p = pf->prog_p))
  7512.             continue;
  7513.         iv->first_temp = 1;
  7514.         iv->temps_written = 0;
  7515.         iv->killop = 0;
  7516.         while(*p != endfileop)
  7517.         {
  7518.             while(*p < labelop)
  7519.             {
  7520.                 if(*p == truthop)
  7521.                 {/* truthops of single chars are unnecessary */
  7522.                   if((p[2]&0xe0) == OPTEMP)
  7523.                   {
  7524.                     if(((PopT)(p+20))->dsize == 1)
  7525.                     {
  7526.                         if(((PopT)(p+8))->tmpnum == ((PopT)(p+20))->tmpnum)
  7527.                         {
  7528.                             if(!(((PopT)(p+20))->atype & A_MEMADDR))
  7529.                                 *p = 0;
  7530.                             break;
  7531.                         }
  7532.                         else
  7533.                         {/* may be needed for code generation */
  7534.                             *p = aliastmpop;
  7535.                         }
  7536.                     }
  7537.                   }
  7538.                 }
  7539.                 if(*p)
  7540.                 {
  7541.                     if(        *p == jmptrueop 
  7542.                         ||  *p == jmpfalseop
  7543.                         ||    *p == ljmptrueop
  7544.                         ||    *p == ljmpfalseop)
  7545.                         read_temp(iv,(PopT)(p+4), 0);
  7546.                     if(*p == retdataop)
  7547.                     {
  7548.                         read_temp(iv, (PopT)p, 0);
  7549.                     }
  7550.                     else
  7551.                     {
  7552.                         last_write = 0;
  7553.                         if((p[1]&0xe0) == OPTEMP)
  7554.                             last_write = write_temp(iv, (PopT)(p+8), *p);
  7555.                         if((p[2]&0xe0) == OPTEMP || (p[2]&0xe0) == OPRET)
  7556.                             read_temp(iv, (PopT)((p+8+(p[1]&0x1f))), last_write);
  7557.                         if((p[3]&0xe0) == OPTEMP || (p[3]&0xe0) == OPRET)
  7558.                             read_temp(iv, (PopT)((p+8+(p[1]&0x1f))+(p[2]&0x1f)), last_write);
  7559.                     }
  7560.                 }
  7561.                 break;
  7562.             }
  7563.             p = POP->next;
  7564.         }
  7565.         do {
  7566.             clean_temps(iv);
  7567.             iv->first_temp -= 0x00010000;
  7568.         } while(iv->first_temp > 0);
  7569.         if(iv->killop)
  7570.         {
  7571.             goto rekill;
  7572.         }
  7573.     }
  7574. }
  7575. static void
  7576. retarget_jmps(Piv iv, int level)
  7577. {
  7578. Pafile pf;
  7579. unsigned char *p;
  7580. int i;
  7581.     for(i = 0; i < iv->numfiles; ++i)
  7582.     {
  7583.         iv->filenum = i;
  7584.         pf = iv->files[i];
  7585.         if(!(p = pf->prog_p))
  7586.             continue;
  7587.         if(pf->header_p->hdr.opt_level >= level)
  7588.             continue;
  7589.     }
  7590. }
  7591.  
  7592.  
  7593. static void
  7594. optimize(Piv iv)
  7595. {
  7596.     eliminate_extraneous_infops(iv, 50);
  7597.     eliminate_unused_temps(iv, 51);
  7598.     retarget_jmps(iv, 52);
  7599. }
  7600. /* ========================== END OPTIMIZATION ============================= */
  7601. /* ====================== BASIC INPUT FILE PROCESSING ====================== */
  7602. static long
  7603. label_insert(Piv iv, long label, int filenum, unsigned char *p)
  7604. {
  7605. long *result;
  7606. struct {
  7607.     long k1;
  7608.     long k2;
  7609. } key;
  7610.  
  7611. struct {
  7612.     long newlabel;
  7613. } val;
  7614.  
  7615.     key.k1 = label;
  7616.     key.k2 = filenum;
  7617.  
  7618.     /* check for duplicate label -- they happen */
  7619.     if(SymFind(iv->labeltbl, &key, &result))
  7620.     {
  7621.         if(*p == labelop)
  7622.             *p = 0; /* kill the instruction */
  7623.         return 0;
  7624.     }
  7625.  
  7626.     val.newlabel = ++iv->lastlabel;
  7627.     SymInsert(iv->labeltbl, &key, &val, 4);
  7628.  
  7629. #if REALLY_NEED_OFFSETS
  7630.     key.k1 = val.newlabel;
  7631.     val.newlabel = -1;
  7632.     SymInsert(iv->newlabeltbl, &key, &val, 4);
  7633. #endif
  7634.  
  7635.     return iv->lastlabel;
  7636. }
  7637. static long
  7638. label_find(Piv iv, long label, int filenum)
  7639. {
  7640. struct {
  7641.     long k1;
  7642.     long k2;
  7643. } key;
  7644.  
  7645. long *result;
  7646.  
  7647.     key.k1 = label;
  7648.     key.k2 = filenum;
  7649.  
  7650.     if(SymFind(iv->labeltbl, &key, &result))
  7651.         return *result;
  7652.     else
  7653.         return 0;
  7654. }
  7655. #if REALLY_NEED_OFFSETS
  7656. static void
  7657. newlabel_insert(Piv iv, long label)
  7658. {
  7659. struct {
  7660.     long k1;
  7661.     long k2;
  7662. } key;
  7663.  
  7664. long *result;
  7665.  
  7666.     key.k1 = label;
  7667.     key.k2 = iv->filenum;
  7668.     if(SymFind(iv->newlabeltbl, &key, &result))
  7669.     {
  7670.         *result = iv->out_offset + iv->func_offset;
  7671.     }
  7672.     else PERROR(pName ":SYSERROR: Label %d not found\n", label);
  7673. }
  7674. static long
  7675. newlabel_fix(Piv iv, long label)
  7676. {
  7677.     if(label)
  7678.     {
  7679.     struct {
  7680.         long k1;
  7681.         long k2;
  7682.     } key ;
  7683.  
  7684.     long *val;
  7685.  
  7686.         key.k1 = label;
  7687.         key.k2 = iv->filenum;
  7688.         if(SymFind(iv->newlabeltbl, &key, &val))
  7689.         {
  7690.             return val[0];
  7691.         }
  7692.     }
  7693.     return label;
  7694. }
  7695. #endif /* REALLY_NEED_OFFSETS */
  7696.  
  7697. static void
  7698. extern_insert(Piv iv, unsigned char *p, int filenum)
  7699. {
  7700. struct {
  7701.     short k1;
  7702.     short k2;
  7703.     long k3;
  7704. } key;
  7705. struct {
  7706.     unsigned char *p;
  7707. } val;
  7708.  
  7709.     key.k1 = GS(POPI->s.symnum);
  7710.     key.k2 = filenum;
  7711.     key.k3 = 0;
  7712.  
  7713.     val.p = p;
  7714.     SymInsert(iv->extrntbl, &key, &val, 4);
  7715. }
  7716. static void
  7717. reloc_insert(Piv iv, int fileno, unsigned char *p)
  7718. {
  7719. struct _rkey key;
  7720. struct _rval val;
  7721.  
  7722.     key.spot = GL(POPI->reloc.spot);    /* reloc target offset */
  7723.     key.fileno = (short)fileno;            /* fileno */
  7724.     key.opcode = *p;                    /* opcode */
  7725.     key.rsize = GL(POPI->reloc.rsize);    /* reloc size */
  7726.  
  7727.     val.p = p;                                /* pointer to input buffer */
  7728.     val.base = (void*)GL(POPI->reloc.base);    /* base of data object pointed to */
  7729.     val.offset = GL(POPI->reloc.offset);    /* offset to be added to base */
  7730.     val.rsym = GS(POPI->reloc.rsym);        /* symbol number if external */
  7731.     SymInsert(iv->reloctbl, &key, &val, 14);
  7732. }
  7733. static void
  7734. data_insert(void *tbl, unsigned long offset,
  7735.             unsigned long size, void *p, void *prevp)
  7736. {
  7737. static long locid = 1;
  7738. struct {
  7739.     unsigned long k1;
  7740.     long k2;
  7741. } key;
  7742. struct {
  7743.     unsigned long size;
  7744.     void *p;
  7745.     void *prevp;
  7746.     long locid;
  7747. } val;
  7748. unsigned char opcode, prevopcode = 0;
  7749.  
  7750.     key.k1 = offset;
  7751.     key.k2 = 0;
  7752.  
  7753.     val.size = size;
  7754.     val.p = p;
  7755.     val.prevp = prevp;
  7756.     val.locid = 0;
  7757.     opcode = *((unsigned char *)p);
  7758.     if(prevp)
  7759.     {
  7760.         prevopcode = *((unsigned char*)prevp);
  7761.         if(        prevopcode != glodatop
  7762.             &&    prevopcode != glofuncop
  7763.             &&    prevopcode != extfuncop
  7764.             &&    prevopcode != globssop)
  7765.         {
  7766.             val.locid = locid++;
  7767.         }    
  7768.     }
  7769.     SymInsert(tbl, &key, &val, sizeof(val));
  7770. }
  7771.  
  7772. static void
  7773. global_insert(Piv iv, Pafile pf, unsigned char *p)
  7774. {
  7775. unsigned long key[2];
  7776. struct _gloval val;
  7777. PopI pp;
  7778. unsigned char opcode = *p;
  7779.  
  7780.     if(opcode == extvarop)
  7781.         pp = POPI;
  7782.     else
  7783.         pp = (PopI)(POP->next+8);
  7784.  
  7785.     key[0] = 0;
  7786.     key[1] = 0;
  7787.  
  7788.     val.symnum = GS(pp->s.symnum);
  7789.     val.symname = pf->symaddr[val.symnum];
  7790.     val.p = p;
  7791.     val.pf = pf;
  7792.     if(val.symnum < 0 || val.symnum >= pf->numsyms)
  7793.     {
  7794.         PERROR(pName ":SYSERROR: BAD SYMNUM=%d opcode=%d\n", val.symnum, opcode);
  7795.     }
  7796.     sym_hash(key, val.symname);
  7797.  
  7798.     /* Duplicate entries are allowed */
  7799.     SymInsert(iv->gbltbl, key, &val, sizeof(val));
  7800. }
  7801.  
  7802. static int
  7803. setup_nodelinks(Piv iv, char *infile_name, void *inbuf, int insize)
  7804. {
  7805. unsigned char *p = inbuf;
  7806. unsigned char *endbuf = inbuf+insize;
  7807. Pafile pf=0;
  7808. int lastline = 0;
  7809. unsigned char *funcp;
  7810. unsigned char *nfuncp;
  7811.  
  7812.     while(p < endbuf && *p != endallop)
  7813.     {
  7814.     unsigned char *q = p;
  7815.         if(iv->debug >= '5')
  7816.         {
  7817.          cfeprintf("OP(%u '%s' p=%p line=%d)\n", *p, oxgenops[*p], p, lastline);
  7818.         }
  7819.         switch(*p)
  7820.         {
  7821.             case headerop:
  7822.                 if(iv->numfiles >= 1024) {
  7823.                     PERROR(pName ": Sorry, too many files\n");
  7824.                 }
  7825.                 pf = iv->files[iv->numfiles] = 
  7826.                     Ccalloc(iv->category, 1, sizeof(struct _afile));
  7827.                 pf->filenum = iv->numfiles++;
  7828.                 pf->file_p = p;
  7829.                 pf->header_p = POPI;
  7830.                 if(iv->strip)
  7831.                 {/* Gonna strip declarations and line numbers */
  7832.                     pf->header_p->hdr.target_debugger = 0;
  7833.                 }
  7834.                 break;
  7835.  
  7836.             case dataop:
  7837.                 pf->size_p = POPI;
  7838.                 pf->thunk_offset = GL(POPI->dat.thunk_offset);
  7839.                 pf->bss_offset = GL(POPI->dat.bss_offset);
  7840.                 break;
  7841.             case gfuncdefop:
  7842.             case sfuncdefop:
  7843.                 if(pf->prog_p == 0)
  7844.                     pf->prog_p = p;
  7845.                 funcp = p;
  7846.                 break;
  7847.             case funcexitop:
  7848.                 PS(((PopI)(funcp+8))->funcdef.tempmax) = GL(POPI->funcexit.tempmax);
  7849.                 break;
  7850.             case nestedfuncdefop:
  7851.                 nfuncp = p;
  7852.                 break;
  7853.             case nestedfuncexitop:
  7854.                 PS(((PopI)(nfuncp+8))->funcdef.tempmax) = GL(POPI->funcexit.tempmax);
  7855.                 break;
  7856.             case segdefop:
  7857.                 if(pf->seg_p == 0)
  7858.                     pf->seg_p = p;
  7859.                 pf->numsegs += 1;
  7860.                 iv->numsegs += 1;
  7861.                 break;
  7862.             case lineop:
  7863.                 lastline = GL( POPI->line.line );
  7864.                 if(iv->strip)
  7865.                     *p = 0;        /* strip line numbers */
  7866.                 break;
  7867.             case declop:
  7868.                 if(iv->strip)
  7869.                 {/* strip declarations */
  7870.                     do {
  7871.                         *p = 0;
  7872.                         q += (long)GL(POP->next);
  7873.                         POP->next = q;
  7874.                         p = q;
  7875.                     } while(*p != endop);                    
  7876.                     *p = 0;
  7877.                 }
  7878.                 else
  7879.                 {
  7880.                     if(pf->decl_p == 0)
  7881.                         pf->decl_p = p;
  7882.                     pf->numdecls += 1;
  7883.                     iv->numdecls += 1;
  7884.                 }
  7885.                 break;
  7886.             case switchidop:
  7887.                 if(pf->switch_p == 0)
  7888.                     pf->switch_p = p;
  7889.                 break;
  7890.             case labelop:
  7891.                 PL( POP->data ) = 
  7892.                         label_insert(iv, GL( POP->data ), pf->filenum, p);
  7893.                 break;            
  7894.             case symbop:
  7895.                 pf->numsyms = GL(POP->data);
  7896.                 iv->numsyms += pf->numsyms;
  7897.                 break;
  7898.             case symblockop:
  7899.                 pf->symtext_p = p + 12;
  7900.                 goto blka;
  7901.             case stringblockop:
  7902.             case datablockop:
  7903.             case mallocblockop:
  7904.             case thunkblockop:
  7905.             {
  7906.             long size;
  7907.                 if(pf->data_p == 0)
  7908.                     pf->data_p = p;
  7909. blka:
  7910.                 size = GL(POP->data);
  7911.                 q += size+((4-(size&3))&3);
  7912.                 break;
  7913.             }
  7914.             case glofuncop:
  7915.             case extfuncop:
  7916.             case glodatop:
  7917.             case globssop:
  7918.             case extvarop:
  7919.             case bssblockop:
  7920.                 if(pf->data_p == 0)
  7921.                     pf->data_p = p;
  7922.                 break;
  7923.             case maxtempop:
  7924.                 pf->maxtemp = GL(POP->data);
  7925.                 pf->maxtempclass = GL(POP->data1);
  7926.                 pf->maxtemp_p = p;
  7927.                 break;
  7928.         }
  7929.         q += (long)GL(POP->next);
  7930.         POP->next = q;
  7931.         p = q;
  7932.     }
  7933.     if(*p != endallop)
  7934.     {
  7935.         PERROR(pName ":ERROR: Malformed input file: %s\n", infile_name);
  7936.     }
  7937.     return 0;
  7938. }
  7939. static void
  7940. setup_syms_decls(Piv iv)
  7941. {
  7942. int i;
  7943.  
  7944.     for(i = 0; i < iv->numfiles; ++i)
  7945.     {
  7946.     int symnum = 0;
  7947.     Pafile pf = iv->files[i];
  7948.     unsigned char *p = pf->file_p;
  7949.     unsigned char *prevp = 0;
  7950.  
  7951.         pf->symaddr = Ccalloc(iv->category, sizeof(void*), pf->numsyms+1);
  7952.         pf->decladdr = Ccalloc(iv->category, sizeof(void*), pf->numdecls+1);
  7953.  
  7954.         while(*p != endfileop)
  7955.         {
  7956.             switch(*p)
  7957.             {
  7958.                 case    symoffsetop:
  7959.                   pf->symaddr[symnum] = pf->symtext_p + GL(POP->data);
  7960.                   ++symnum;
  7961.                   break;
  7962.  
  7963.                 case    declop:
  7964.                   pf->decladdr[GS(POPI->dcl.declnum)] = p;
  7965.                   break;
  7966.  
  7967.                 case    relocop:
  7968.                 case    extlocop:
  7969.                   ++pf->numrelocs;
  7970.                   reloc_insert(iv, i, p);
  7971.                   break;
  7972.  
  7973.                 case    glodatop:
  7974.                 case    globssop:
  7975.                 case    glofuncop:
  7976.                 case    extfuncop:
  7977.                   global_insert(iv, pf, p);
  7978.                   break;
  7979.  
  7980.                 case    extvarop:
  7981.                   extern_insert(iv, p, i);
  7982.                   global_insert(iv, pf, p);
  7983.                   break;
  7984.  
  7985.                 case    stringblockop:
  7986.                 case    datablockop:
  7987.                 case    mallocblockop:
  7988.                 case    thunkblockop:
  7989.                 case    bssblockop:
  7990.                   if(!pf->datatbl)
  7991.                     pf->datatbl = NewSymTable(iv->category, 0);  /* sorted */
  7992.  
  7993.                   data_insert(pf->datatbl,GL(DATI.offset),GL(DATI.size),
  7994.                               p, prevp);
  7995.                   if(*p == thunkblockop) {
  7996.                     PL(POP->data5) = label_find(iv, GL(POP->data5), i);
  7997.                   }
  7998.                   break;
  7999.  
  8000.                 case    jmploopop:
  8001.                 case    jmpcontinueop:
  8002.                 case    jmpbreakop:
  8003.                 case    jmpgotoop:
  8004.                 case    jmptrueop:
  8005.                 case    jmpfalseop:
  8006.                 case    ljmptrueop:
  8007.                 case    ljmpfalseop:
  8008.                 case    funcstartop:
  8009.                 case    funcstopop:
  8010.                 case    casevalop:
  8011.                 case    switchop:
  8012.                   PL(POP->data) = label_find(iv, GL(POP->data), i);
  8013.                   break;
  8014.             }
  8015.             prevp = p;
  8016.             p = POP->next;
  8017.         }
  8018.     }
  8019. }
  8020. static int
  8021. sym_insert(Piv iv, char *symname, int symnum)
  8022. {/* Used only for combining symbols in link phase */
  8023. struct {
  8024.     char *symname;
  8025.     int symnum;
  8026. } *valp;
  8027.  
  8028.     if(StringInsert(iv->symtbl, symname, &valp))
  8029.         return -valp->symnum;    /* MATCH */
  8030.     valp->symnum = symnum;
  8031.     return symnum;
  8032. }
  8033. static void
  8034. combine_syms_decls(Piv iv)
  8035. {
  8036. int i,j;
  8037. Pafile pf;
  8038. int numsyms;
  8039. int numdecls;
  8040.  
  8041.     /* COMBINE SYMBOLS */
  8042.     pf = iv->files[0];
  8043.     numsyms = pf->numsyms;
  8044.     pf->symtran = Ccalloc(iv->category, sizeof(short), pf->numsyms+1);
  8045.     memcpy(iv->symaddr, pf->symaddr, sizeof(void*) * numsyms);
  8046.  
  8047.  
  8048.     for(i = 0; i < numsyms; ++i)
  8049.     {/* file 0 */
  8050.         sym_insert(iv, pf->symaddr[i], i);
  8051.         pf->symtran[i] = i;
  8052.     }
  8053.     for(i = 1; i < iv->numfiles; ++i)
  8054.     {
  8055.     int start;
  8056.  
  8057.         pf = iv->files[i];
  8058.         pf->symtran = Ccalloc(iv->category, sizeof(short), pf->numsyms+1);
  8059.         if(pf->header_p->hdr.target_debugger)
  8060.             start = 1;
  8061.         else
  8062.             start = 3;
  8063.         for(j = start; j < pf->numsyms; ++j)
  8064.         {
  8065.         int k;
  8066.           if((k = sym_insert(iv, pf->symaddr[j], numsyms)) > 0)
  8067.           { /* new entry */
  8068.             iv->symaddr[numsyms++] = pf->symaddr[j];
  8069.             pf->symtran[j] = k;
  8070.           }
  8071.           else pf->symtran[j] = -k;
  8072.         }
  8073.     }
  8074.     iv->numsyms = numsyms;
  8075.  
  8076.     /* COMBINE DECLARATIONS */
  8077.     pf = iv->files[0];
  8078.     numdecls = pf->numdecls;
  8079.     pf->decltran = Ccalloc(iv->category, sizeof(short), numdecls+1);
  8080.     memcpy(iv->decladdr, pf->decladdr, sizeof(void*) * numdecls);
  8081.     for(i = 0; i < numdecls; ++i)
  8082.     {/* file 0 */
  8083.         pf->decltran[i] = i;
  8084.     }
  8085.     for(i = 1; i < iv->numfiles; ++i)
  8086.     {
  8087.         pf = iv->files[i];
  8088.         pf->decltran = Ccalloc(iv->category, sizeof(short), pf->numdecls+1);
  8089.         if(pf->numdecls < 21)
  8090.             continue;
  8091.         for(j = 1; j <= 21; ++j)
  8092.             pf->decltran[j] = j;
  8093.         for(j = 22; j < pf->numdecls; ++j) {
  8094.             iv->decladdr[numdecls] = pf->decladdr[j];
  8095.             pf->decltran[j] = numdecls++;
  8096.         }
  8097.     }
  8098.     iv->numdecls = numdecls;
  8099. }
  8100.  
  8101. static void
  8102. link_dups(Piv iv, int dupcnt, struct _gloval *valp[])
  8103. {
  8104. int i;
  8105. int vars[5] = {0,0,0,0,0};
  8106. unsigned long cdsize = 0;
  8107. unsigned long cdoffset = 0;
  8108. short cdfile = 0;
  8109. int cdnum = 0;
  8110. short segid = 0;
  8111.  
  8112. #define GDAT vars[0]
  8113. #define GBSS vars[1]
  8114. #define GFUNC vars[2]
  8115. #define EVAR vars[3]
  8116. #define EFUNC vars[4]
  8117.  
  8118.     /* Count the types of matches */
  8119.     for(i = 0; i <= dupcnt; ++i)
  8120.         vars[*(valp[i]->p) - glodatop] += 1;
  8121.  
  8122.     /* Check for errors */
  8123.     if(        GDAT > 1 
  8124.         ||    GFUNC > 1
  8125.         ||    (GFUNC && (GDAT || GBSS || EVAR))
  8126.         ||    (EFUNC && (GDAT || GBSS || EVAR)))
  8127.     {
  8128.         ++iv->errors;
  8129.         for(i = 0; i < dupcnt; ++i)
  8130.         {
  8131.             PWARN(pName ": Symbol `%s' multiply defined or mistyped.\n",
  8132.                   valp[i]->symname);
  8133.             PWARN(pName":  In file: `%s'\n", valp[i]->pf->symaddr[INFILE_SYMNUM]);
  8134.         }
  8135.         return;
  8136.     }
  8137.     if(EFUNC && GFUNC)
  8138.     {/* match up functions */
  8139.     Pop dp;
  8140.         for(i = 0; i <= dupcnt; ++i)
  8141.           if(*(valp[i]->p) == glofuncop)
  8142.             break;
  8143.         dp = (Pop)((Pop)valp[i]->p)->next;    /* points to thunkblockop */
  8144.  
  8145.         cdoffset = GL(dp->data1);            /* save this offset */
  8146.         cdfile = valp[i]->pf->filenum;        /* save this file */
  8147.         for(i = 0; i <= dupcnt; ++i)
  8148.         {
  8149.           if(*(valp[i]->p) == extfuncop)
  8150.           {
  8151.             *(valp[i]->p) = 0;                    /* convert to nilop */
  8152.             dp = (Pop)((Pop)valp[i]->p)->next;    /* points to thunkblockop */
  8153.  
  8154.             /* Kill the thunkblock */
  8155.             *((char*)dp) = 0;
  8156.             PL(dp->data4) = cdoffset;            /* use this offset for access */
  8157.             PS(((short*)dp)[1]) = cdfile;        /* fileno to unused slots */
  8158.           }
  8159.         }
  8160.     }
  8161.     else if(EFUNC)
  8162.     {/* multiple references to external function */
  8163.     Pop    dp = (Pop)((Pop)valp[0]->p)->next;    /* points to first thunkblockop */
  8164.  
  8165.         cdoffset = GL(dp->data1);            /* save first offset */
  8166.         cdfile = valp[0]->pf->filenum;        /* save first file */
  8167.         for(i = 1; i <= dupcnt; ++i)
  8168.         {/* Kill all thunkblocks except the first */
  8169.             *(valp[i]->p) = 0;                    /* convert to nilop */
  8170.             dp = (Pop)((Pop)valp[i]->p)->next;    /* points to thunkblockop */
  8171.             *((char*)dp) = 0;
  8172.             PL(dp->data4) = cdoffset;            /* use this offset for access */
  8173.             PS(((short*)dp)[1]) = cdfile;        /* fileno to unused slots */
  8174.         }
  8175.     }
  8176.     else if(GBSS)
  8177.     {/* comdefs */
  8178.     int multsize = 0;
  8179.  
  8180.         /* PICK THE BIGGEST GLOBAL BSS (comdef) */
  8181.         for(i = 0; i <= dupcnt; ++i)
  8182.         {
  8183.         Pop dp = (Pop)((Pop)valp[i]->p)->next;    /* points to bssblockop */
  8184.           if((short)dp->data4 && segid == 0)
  8185.           {
  8186.             segid = (short)dp->data4;
  8187.           }
  8188.           else if((short)dp->data4 && (short)dp->data4 != segid)
  8189.           {
  8190.             ++iv->errors;
  8191.             PWARN(pName ": Variable `%s' defined in multiple segments.\n",
  8192.                 valp[i]->symname);
  8193.             PWARN(pName ":  In file: `%s'\n", valp[i]->pf->symaddr[INFILE_SYMNUM]);
  8194.           }
  8195.           if(*(valp[i]->p) == globssop)
  8196.           {
  8197.           long size = GL(dp->data);
  8198.             if(cdsize && size != cdsize)
  8199.                 multsize = 1;
  8200.             if(size > cdsize) {
  8201.                 cdsize = size;
  8202.                 cdoffset = GL(dp->data1);
  8203.                 cdfile = valp[i]->pf->filenum;
  8204.                 cdnum = i;
  8205.             }
  8206.           }
  8207.         }
  8208.         if(GDAT)
  8209.         {
  8210.           /* INITIALIZED DATA WILL ALWAYS OVERRIDE BSS */
  8211.           for(i = 0; i <= dupcnt; ++i)
  8212.           {
  8213.             if(*(valp[i]->p) == glodatop)
  8214.             {
  8215.             Pop dp = (Pop)((Pop)valp[i]->p)->next;    /* points to datablockop */
  8216.             long size = GL(dp->data);
  8217.               if(cdsize && size != cdsize)
  8218.                   multsize = 1;
  8219.               if(size < cdsize)
  8220.               {
  8221.             ++iv->errors;
  8222.             PWARN(pName ": Initialized variable `%s' of size (%d)\n",
  8223.               valp[i]->symname, size);
  8224.             PWARN(pName ":  In file: `%s'\n",
  8225.               valp[i]->pf->symaddr[INFILE_SYMNUM]);
  8226.             PWARN(pName ":  Is incommensurate with common size (%d).\n",
  8227.               cdsize);
  8228.               }
  8229.               else
  8230.               {
  8231.                   cdsize = size;
  8232.                   cdoffset = GL(dp->data1);
  8233.                   cdfile = valp[i]->pf->filenum;
  8234.                   cdnum = i;
  8235.               }
  8236.             }
  8237.           }
  8238.         }
  8239.         if(multsize)
  8240.         {
  8241.           PWARN(pName ":warning: Common Variable `%s' has multiple sizes.\n",
  8242.               valp[0]->symname);
  8243.           for(i = 0; i <= dupcnt; ++i)
  8244.           {
  8245.           unsigned char opcode = *(valp[i]->p);
  8246.             if(opcode == globssop || opcode == glodatop)
  8247.             {
  8248.                 PWARN(pName ":warning:Size=%d in file: `%s'\n",
  8249.                   GL(((Pop)((Pop)valp[i]->p)->next)->data),
  8250.                   valp[i]->pf->symaddr[INFILE_SYMNUM]);
  8251.             }
  8252.           }
  8253.         }
  8254.         /* FINALLY, LINK COMMONS TO THE CHOSEN ONE */
  8255.         for(i = 0; i <= dupcnt; ++i)
  8256.         {
  8257.           if(i != cdnum && *(valp[i]->p) == globssop)
  8258.           {
  8259.           Pop dp = (Pop)((Pop)valp[i]->p)->next;    /* points to bssblockop */
  8260.  
  8261.             *(valp[i]->p) = 0;            /* globssop becomes nilop */
  8262.             *((char*)dp) = 0;            /* bssblockop becomes nilop */
  8263.             PL(dp->data4) = cdoffset;    /* use this new offset for access */
  8264.             PS(((short*)dp)[1]) = cdfile;    /* put fileno in unused slots */
  8265.           }
  8266.         }
  8267.     }
  8268.     else if(GDAT)
  8269.     {
  8270.         for(i = 0; i <= dupcnt; ++i)
  8271.         {
  8272.         Pop dp = (Pop)((Pop)valp[i]->p)->next;    /* points to datablockop */
  8273.           if((short)dp->data4 && segid == 0)
  8274.           {
  8275.             segid = (short)dp->data4;
  8276.           }
  8277.           else if((short)dp->data4 && (short)dp->data4 != segid)
  8278.           {
  8279.             ++iv->errors;
  8280.             PWARN(pName ": Variable `%s' defined in multiple segments.\n",
  8281.                 valp[i]->symname);
  8282.             PWARN(pName ": In file: `%s'\n", valp[i]->pf->symaddr[INFILE_SYMNUM]);
  8283.           }
  8284.           if(*(valp[i]->p) == glodatop)
  8285.           {
  8286.             cdsize = GL(dp->data);
  8287.             cdoffset = GL(dp->data1);
  8288.             cdfile = valp[i]->pf->filenum;
  8289.             cdnum = i;
  8290.             break;
  8291.           }
  8292.         }
  8293.     }
  8294.     if(EVAR && (GDAT || GBSS))
  8295.     {/* match up variables */
  8296.         /* LINK EXTERNS TO THE CHOSEN ONE */
  8297.         for(i = 0; i <= dupcnt; ++i)
  8298.         {
  8299.           if(*(valp[i]->p) == extvarop)
  8300.           {
  8301.           Pop dp = (Pop)valp[i]->p;
  8302.  
  8303.             *((char*)dp) = 0;            /* extvarop becomes nilop */
  8304.             PL(dp->data1) = cdoffset;    /* use this new offset for access */
  8305.             PS(((short*)dp)[1]) = cdfile;    /* put fileno in unused slots */
  8306.             PS(dp->data4) = segid;
  8307.             break;
  8308.           }
  8309.         }
  8310.     }
  8311. #undef GDAT
  8312. #undef GBSS
  8313. #undef GFUNC
  8314. #undef EVAR
  8315. #undef EFUNC
  8316.  
  8317. }
  8318. static void
  8319. link_globals(Piv iv)
  8320. {
  8321.     if(SymHead(iv->gbltbl))
  8322.     {
  8323.     struct _gloval *valp[1024];    /* pointers to symtable value structs */
  8324.  
  8325.       /* Pass over the sorted symbol table and process duplicate entries */
  8326.       while(SymNext(iv->gbltbl))
  8327.       {
  8328.       unsigned long *key;
  8329.       long mark[2];                            /* Table position saver */
  8330.       int dupcnt = 0;
  8331.         SymKey(iv->gbltbl, &key);            /* Pointer to first key */
  8332.         SymValue(iv->gbltbl, &valp[0]);        /* Pointer to first value */
  8333.  
  8334.         while(SymMarkNext(iv->gbltbl, mark))
  8335.         {/* Look forward for duplicates */
  8336.         unsigned long *key1;
  8337.           SymKey(iv->gbltbl, &key1);                /* Pointer to next key */
  8338.           if(KEYEQ(key, key1))
  8339.           {/* Hashed keys match, check the strings */
  8340.             SymValue(iv->gbltbl, &valp[dupcnt+1]);    /* Pointer to next value */
  8341.             if(!strcmp(valp[dupcnt]->symname, valp[dupcnt+1]->symname))
  8342.             {/* Duplicate entry found */
  8343.                 ++dupcnt;
  8344.                 continue;
  8345.             }
  8346.           }
  8347.           break;
  8348.         }
  8349.         if(dupcnt > 0)
  8350.         {/* Process a collection of duplicate symbol names */
  8351.           link_dups(iv, dupcnt, valp);
  8352.         }
  8353.         SymSetMark(iv->gbltbl, mark);
  8354.  
  8355.       }/* END: while(SymNext) */
  8356.     }/* END: if(SymHead) */
  8357. }
  8358. static void
  8359. realloc_data(Piv iv)
  8360. {
  8361. int i;
  8362. Pafile pf;
  8363. unsigned char *p, *prevp;
  8364. unsigned long offset = 0;
  8365.  
  8366.     iv->datatbl = NewSymTable(iv->category, 0);     /* sorted table */
  8367.  
  8368.     for(i = 0; i < iv->numfiles; ++i)
  8369.     {
  8370.         pf = iv->files[i];
  8371.         p = pf->data_p;
  8372.         prevp = 0;
  8373.         while(*p != endfileop)
  8374.         {
  8375.             if(        *p == datablockop
  8376.                 ||    *p == mallocblockop
  8377.                 ||    *p == stringblockop)
  8378.             {
  8379.                 PL(POP->data1) = offset;                
  8380.                 data_insert(iv->datatbl, offset, GL(POP->data), p, prevp);
  8381.                 offset += GL(POP->data);
  8382.                 ROUNDUP(offset, 4);
  8383.             }
  8384.             prevp = p;
  8385.             p = POP->next;
  8386.         }
  8387.     }
  8388.     iv->thunk_offset = offset;
  8389.  
  8390.     for(i = 0; i < iv->numfiles; ++i)
  8391.     {
  8392.         pf = iv->files[i];
  8393.         p = pf->data_p;
  8394.         prevp = 0;
  8395.         while(*p != endfileop)
  8396.         {
  8397.             if(*p == thunkblockop)
  8398.             {
  8399.                 PL(POP->data1) = offset;
  8400.                 data_insert(iv->datatbl, offset, GL(POP->data), p, prevp);
  8401.                 offset += GL(POP->data);
  8402.                 ROUNDUP(offset, 4);
  8403.             }
  8404.             prevp = p;
  8405.             p = POP->next;
  8406.         }
  8407.     }
  8408.     iv->bss_offset = offset;
  8409.  
  8410.     for(i = 0; i < iv->numfiles; ++i)
  8411.     {
  8412.         pf = iv->files[i];
  8413.         p = pf->data_p;
  8414.         prevp = 0;
  8415.         while(*p != endfileop)
  8416.         {
  8417.             if(*p == bssblockop)
  8418.             {
  8419.                 PL(POP->data1) = offset;
  8420.                 data_insert(iv->datatbl, offset, GL(POP->data), p, prevp);
  8421.                 offset += GL(POP->data);
  8422.                 ROUNDUP(offset, 4);
  8423.             }
  8424.             prevp = p;
  8425.             p = POP->next;
  8426.         }
  8427.     }
  8428.     iv->total_size = offset;
  8429. }
  8430. static void
  8431. reset_data_relocs(Piv iv)
  8432. {/* Pass over initialized data and set new offsets in each relocatable slot */
  8433. struct _data {/* datatbl node */
  8434. /* value area 16 bytes */
  8435.     unsigned long size;
  8436.     unsigned char *p;
  8437.     unsigned char opcode;
  8438.     unsigned char unused[7];
  8439. /* key area 8 bytes */
  8440.     unsigned long offset;
  8441.     long unused1;
  8442. };
  8443.     /* PASS OVER ALL THE ENTRIES IN `reloctbl' */
  8444.     if(SymHead(iv->reloctbl))
  8445.     {
  8446.         while(SymNext(iv->reloctbl))
  8447.         {
  8448.         struct _rkey *kp;
  8449.         struct _rval *vp;
  8450.         struct _data *dp, *ndp;
  8451.         unsigned char *p;
  8452.         Pafile pf, npf;
  8453.         unsigned long object_base;
  8454.         int noset = 0;
  8455.  
  8456.           SymKey(iv->reloctbl, &kp);
  8457.           SymValue(iv->reloctbl, &vp);
  8458.           npf = pf = iv->files[kp->fileno];    /* pointer to file struct */
  8459.           p = vp->p;        /* pointer to relocop in input buffer */
  8460.  
  8461.           if(kp->opcode == extlocop)
  8462.           {/* External variable */
  8463.           short key[4];
  8464.           struct {
  8465.           unsigned char *p;    /* pointer to extvarop in input buffer */
  8466.           } *ep;
  8467.             key[0] = vp->rsym;         /* external symbol number */
  8468.             key[1] = pf->filenum;
  8469.             key[2] = 0;
  8470.             key[3] = 0;
  8471.  
  8472.             /* LOOK UP THE EXTERNAL SYMBOL */
  8473.             if(SymFind(iv->extrntbl, key, &ep) && *(ep->p) == 0)
  8474.             {/* symbol exists and the extvarop was filled in */
  8475.  
  8476.                 npf = iv->files[GS( ((short*)(ep->p))[1] )];
  8477.                 PL( POPI->reloc.base ) = GL( ((Pop)(ep->p))->data1 );
  8478.                 *p = relocop;    /* switch input file from `extlocop' */
  8479.             }
  8480.             else
  8481.             {/* Not found or not filled in, leave it alone */
  8482.                 noset = 1;
  8483.             }
  8484.           }
  8485.  
  8486.           /* RESET THE ENTRY IN THE INITIALIZED DATA SLOT */
  8487.           if(SymFindRange(pf->datatbl, &kp->spot, &dp))
  8488.           {/* This entry describes a block of data containg the reloc target */
  8489.           unsigned char *ip = dp->p;    /* points to input buffer */
  8490.           unsigned long extra = kp->spot - dp->offset; /* offset into data */
  8491.  
  8492.  
  8493.             /* Reset the relocop target in the input file */
  8494.  
  8495.             PL( POPI->reloc.spot ) = GL( ((PopI)(ip+8))->s.offset ) + extra;
  8496.             if(noset)
  8497.                 continue;
  8498.  
  8499.             if(kp->rsize == 4)
  8500.             {/* 32 bit relocation */
  8501.             unsigned long *lp;
  8502.  
  8503.                 lp = (unsigned long*)(ip+24+extra);    /* pointer to target */
  8504.                 object_base = GL( POPI->reloc.base );
  8505.  
  8506.                 /* Find the object that the target points to */
  8507. relink32:
  8508.                 if(SymFindRange(npf->datatbl, &object_base, &ndp))
  8509.                 {
  8510.                     if(*(ndp->p) == 0)
  8511.                     {/* The found object is a discarded thunkblock, relink */
  8512.                         npf = iv->files[GS( ((short*)(ndp->p))[1] )];
  8513.                         object_base = GL( ((Pop)(ndp->p))->data4 );
  8514.                         goto relink32;
  8515.                     }
  8516.                     else
  8517.                     {/* Use the new offset in the input file */
  8518.  
  8519.                         object_base = GL( ((Pop)(ndp->p))->data1 );
  8520.                     }
  8521.                     PL( POPI->reloc.base ) = object_base; /* the `relocop' */
  8522.                     PL(*lp) = object_base + GL( POPI->reloc.offset );/* data */
  8523.                     vp->base = lp;
  8524.                 }
  8525.                 else
  8526.                 {
  8527.                     ++iv->errors;
  8528.                     PWARN(pName ":syserr: 32 bit object at offset %d not found\n",object_base);
  8529.                 }
  8530.             }
  8531.             else if(kp->rsize == 2)
  8532.             {/* 16 bit relocation (MORE WORK NEEDED) */
  8533.             unsigned short *sp;
  8534.  
  8535.                 sp = (unsigned short*)(ip+24+extra);    /* pointer to target */
  8536.                 object_base = GL( POPI->reloc.base );
  8537. relink16:
  8538.                 if(SymFindRange(npf->datatbl, &object_base, &ndp))
  8539.                 {
  8540.                     if(*(ndp->p) == 0)
  8541.                     {/* The found object is a discarded thunkblock, relink */
  8542.                         npf = iv->files[GS( ((short*)(ndp->p))[1] )];
  8543.                         object_base = GL( ((Pop)(ndp->p))->data4 );
  8544.                         goto relink16;
  8545.                     }
  8546.                     else
  8547.                     {/* Use the new offset in the input file */
  8548.  
  8549.                         object_base = GL( ((Pop)(ndp->p))->data1 );
  8550.                     }
  8551.                     PL( POPI->reloc.base ) = object_base; /* the `relocop' */
  8552.                     PS(*sp) = object_base + GL( POPI->reloc.offset );/* data */
  8553.                 }
  8554.                 else
  8555.                 {
  8556.                     ++iv->errors;
  8557.                     PWARN(pName ":syserr: 16 bit object at offset %d not found\n", object_base);
  8558.                 }
  8559.  
  8560.             }
  8561.           }
  8562.           else /* !SymFindRange */
  8563.           {
  8564.             ++iv->errors;
  8565.             PWARN(pName ":syserr: reloc not found at %d in file %d\n", 
  8566.                     kp->spot, kp->fileno);
  8567.           }
  8568.         }/* END: While(SymNext) */
  8569.     }/* END: if(SymHead) */
  8570. }
  8571. static void
  8572. reset_offset(Piv iv, Pafile pf, PopA pa)
  8573. {/* All offsets are guaranteed to be inside objects */
  8574. struct _data {/* datatbl node */
  8575. /* value area 16 bytes */
  8576.     unsigned long size;
  8577.     unsigned char *p;
  8578.     unsigned long unused[2];
  8579. /* key area 8 bytes */
  8580.     unsigned long offset;
  8581.     long unused1;
  8582. };
  8583.  
  8584. unsigned long offset;
  8585. struct _data *dp;
  8586. unsigned long object_base;
  8587. long extra;
  8588. unsigned short atype;
  8589. short symnum;
  8590.  
  8591.     offset = GL( pa->offset );
  8592.     atype = GS( pa->atype );
  8593.     symnum = GS( pa->symnum );
  8594.  
  8595.     PS( pa->symnum ) = pf->symtran[symnum];
  8596.     PS( pa->declnum ) = pf->decltran[GS(pa->declnum)];
  8597.  
  8598.     if(atype & A_EXTERN)
  8599.     {
  8600.     short key[4];
  8601.     struct {
  8602.     unsigned char *p;    /* pointer to extvarop in input buffer */
  8603.     } *ep;
  8604.         key[0] = symnum;         /* external symbol number */
  8605.         key[1] = pf->filenum;
  8606.         key[2] = 0;
  8607.         key[3] = 0;
  8608.  
  8609.             /* LOOK UP THE EXTERNAL SYMBOL */
  8610.         if(!SymFind(iv->extrntbl, key, &ep) && *(ep->p))
  8611.         {/* symbol exists and the extvarop was filled in */
  8612.  
  8613.             pf = iv->files[GS( ((short*)(ep->p))[1] )];
  8614.             offset += GL( ((Pop)(ep->p))->data1 );
  8615.         }
  8616.         else
  8617.         {/* Not found or not filled in, leave it alone */
  8618.  
  8619.             return;
  8620.         }
  8621.     }
  8622.     extra = 0;    /* first time through */
  8623.  
  8624.     /* Find the object that the offset points to */
  8625. relink:
  8626.     if(SymFindRange(pf->datatbl, &offset, &dp))
  8627.     {
  8628.         if(extra == 0)
  8629.             extra = offset - dp->offset;
  8630.         object_base = dp->offset;
  8631.  
  8632.         if(*(dp->p) == 0)
  8633.         {/* The found object is a discarded block, relink */
  8634.             pf = iv->files[GS( ((short*)(dp->p))[1] )];
  8635.             offset = GL( ((Pop)(dp->p))->data4 );
  8636.             goto relink;
  8637.         }
  8638.         else
  8639.         {/* Use the adjusted offset in the input buffer */
  8640.  
  8641.             object_base = GL( ((Pop)(dp->p))->data1 );
  8642.         }
  8643.         PL( pa->offset ) = object_base + extra;
  8644.         if(atype & A_EXTERN)
  8645.         {
  8646.             PS( pa->atype ) = atype & ~A_EXTERN;        
  8647.         }
  8648.     }
  8649.     else
  8650.     {
  8651.         ++iv->errors;
  8652.         PWARN(pName ":syserr: object `%s' at offset %d not found\n", 
  8653.             pf->symaddr[symnum], offset);
  8654.     }
  8655. }
  8656. static void
  8657. reset_text_relocs(Piv iv)
  8658. {/* Pass over text and set new offsets in instructions that reference data */
  8659. int i;
  8660.  
  8661.     for(i = 0; i < iv->numfiles; ++i)
  8662.     {
  8663.     Pafile pf;
  8664.     unsigned char *p;
  8665.  
  8666.         pf = iv->files[i];
  8667.         if(!(p = pf->prog_p))
  8668.             continue;
  8669.  
  8670.         while(*p != endfileop)
  8671.         {
  8672.             if(*p && *p <= (unsigned char)100)
  8673.             {/* instruction */
  8674.             int inc = 8;
  8675.                 if((p[1]&0xe0) == OPDATA)
  8676.                     reset_offset(iv, pf, POPA);
  8677.                 inc += (p[1]&0x1f);
  8678.                 if((p[2]&0xe0) == OPDATA)
  8679.                     reset_offset(iv, pf, POPA);
  8680.                 inc += (p[2]&0x1f);
  8681.                 if((p[3]&0xe0) == OPDATA)
  8682.                     reset_offset(iv, pf, POPA);
  8683.             }
  8684.             p = POP->next;                
  8685.         }
  8686.     }
  8687.  
  8688. }
  8689. static void *
  8690. seg_find(Piv iv, int id)
  8691. {
  8692. long key[2];
  8693. void **result;
  8694.  
  8695.     if(iv->segtbl)
  8696.     {
  8697.         key[0] = id;
  8698.         key[1] = 0;
  8699.         if(SymFind(iv->segtbl, key, &result))
  8700.             return *result;
  8701.     }
  8702.     return 0;    
  8703. }
  8704. static void
  8705. check_seg(Piv iv, unsigned char *p, Pafile pf)
  8706. {
  8707. PopI np, op;
  8708.     if(!(iv->segtbl))
  8709.     {
  8710.         iv->segtbl = NewSymTable(iv->category, 111);
  8711.     }
  8712.     if((op = seg_find(iv, GS(POPI->segdef.segid))))
  8713.     {
  8714.         np = POPI;
  8715.         if(        GL(np->segdef.v1) == GL(op->segdef.v1)
  8716.             &&    GL(np->segdef.v2) == GL(op->segdef.v2)
  8717.             &&    GL(np->segdef.v3) == GL(op->segdef.v3))
  8718.         {/* segments of same name have the same values */
  8719.             *p = 0;    /* kill the new definition */
  8720.             return;
  8721.         }
  8722.         else
  8723.         {/* segments of same name have different values */
  8724.             ++iv->errors;
  8725.             PWARN(pName ":Segment `%s' defined differently.\n",
  8726.                 iv->symaddr[GS(POPI->segdef.segid)]);
  8727.             PWARN(pName ":  In file: `%s'\n", pf->symaddr[INFILE_SYMNUM]);
  8728.             return;
  8729.         }
  8730.     }
  8731.     else
  8732.     {
  8733.     long key[2];
  8734.     PopI pp = POPI;
  8735.         key[0] = GS(POPI->segdef.segid);
  8736.         key[1] = 0;
  8737.         SymInsert(iv->segtbl, key, &pp, 4);
  8738.     }
  8739. }
  8740. static void
  8741. reset_syms_decls(Piv iv)
  8742. {
  8743. int i;
  8744.     for(i = 0; i < iv->numfiles; ++i)
  8745.     {
  8746.     Pafile pf;
  8747.     unsigned char *p;
  8748.  
  8749.         pf = iv->files[i];
  8750.         p = pf->file_p;
  8751.  
  8752.         while(*p != endfileop)
  8753.         {
  8754.           if(*p == segdefop)
  8755.           {
  8756.             PS(POPI->segdef.segid) = pf->symtran[GS(POPI->segdef.segid)];
  8757.             check_seg(iv, p, pf);
  8758.           }
  8759.           else if(i > 0)
  8760.           {
  8761.             switch(*p)
  8762.             {
  8763.                 case    declop:
  8764.                     if(GS(POPI->dcl.declnum) < 22)
  8765.                     {/* kill the base declarations */
  8766.                         *p = 0;
  8767.                         p = POP->next;                
  8768.                         *p = 0;
  8769.                     }
  8770.                     else
  8771.                      PS(POPI->dcl.declnum)=pf->decltran[GS(POPI->dcl.declnum)];
  8772.                     break;
  8773.                 case    extlocop:
  8774.                     PS(POPI->reloc.rsym) = pf->symtran[GS(POPI->reloc.rsym)];
  8775.                     break;
  8776.                 case    gfuncdefop:
  8777.                 case    sfuncdefop:
  8778.                     if(pf->numsegs)
  8779.                     PS(POPI->funcdef.segid) = pf->symtran[GS(POPI->funcdef.segid)];
  8780.                 case    nestedfuncdefop:
  8781.                     PL(POPI->funcdef.symnum) = pf->symtran[GL(POPI->funcdef.symnum)];
  8782.                     break;
  8783.                 case    bssblockop:
  8784.                 case    datablockop:
  8785.                     if(pf->numsegs)
  8786.                     PS( POPI->s.segid ) = pf->symtran[GS(POPI->s.segid)];
  8787.                 case    stringblockop:
  8788.                 case    mallocblockop:
  8789.                 case    thunkblockop:
  8790.                 case    extvarop:
  8791.                     PS( POPI->s.symnum ) = pf->symtran[GS(POPI->s.symnum)];
  8792.                     PS( POPI->s.declnum ) = pf->decltran[GS(POPI->s.declnum)];
  8793.                     break;
  8794.                 case    memberinfop:
  8795.                 case    bfieldinfop:
  8796.                     PS(POPI->memb.symnum) = pf->symtran[GS(POPI->memb.symnum)];
  8797.                     PS(POPI->memb.declnum) = pf->decltran[GS(POPI->memb.declnum)];
  8798.                     PS(POPI->memb.cdeclnum) = pf->decltran[GS(POPI->memb.cdeclnum)];
  8799.                     break;
  8800.                 case    structinfop:
  8801.                     PS(POPI->suinf.symnum) = pf->symtran[GS(POPI->suinf.symnum)];
  8802.                     break;
  8803.                 case    funcptrinfop:
  8804.                 case    ptrinfop:
  8805.                     PS(POPI->ptrinf.declnum) = pf->decltran[GS(POPI->ptrinf.declnum)];
  8806.                     break;
  8807.                 case    funcinfop:
  8808.                     PS(POPI->funcd.declnum) = pf->decltran[GS(POPI->funcd.declnum)];
  8809.                     PS(POPI->funcd.symnum) = pf->symtran[GS(POPI->funcd.symnum)];
  8810.                     break;
  8811.                 case    arrayinfop:
  8812.                     PS(POPI->ary.declnum) = pf->decltran[GS(POPI->ary.declnum)];
  8813.                     break;
  8814.                 case    lineop:
  8815.                     PL(POPI->line.filenamenum) = pf->symtran[GL(POPI->line.filenamenum)];
  8816.                     break;
  8817.             }/* END: switch(*p) */
  8818.           }/* END: i > 0 */
  8819.           p = POP->next;                
  8820.         }
  8821.     }
  8822. }
  8823. static int
  8824. link_files(Piv iv)
  8825. {
  8826.     iv->extrntbl = NewSymTable(iv->category, 4092);    /* hashed table */
  8827.     iv->reloctbl = NewSymTable(iv->category, 4092); /* hashed table */
  8828.     iv->gbltbl = NewSymTable(iv->category, 0);    /* sorted table */
  8829.  
  8830.     setup_syms_decls(iv);
  8831.  
  8832.     if(iv->numfiles > 1)
  8833.     {
  8834.         iv->symaddr = Ccalloc(iv->category, sizeof(void*), iv->numsyms+1);
  8835.         iv->decladdr = Ccalloc(iv->category, sizeof(void*), iv->numdecls+1);
  8836.         iv->symtbl = NewSymTable(iv->category, 0); /* sorted table */
  8837.         combine_syms_decls(iv);
  8838.  
  8839.         link_globals(iv);
  8840.         realloc_data(iv);
  8841.         reset_data_relocs(iv);
  8842.         reset_text_relocs(iv);
  8843.  
  8844.         reset_syms_decls(iv);
  8845.     }
  8846.     else
  8847.     {
  8848.         iv->symaddr = iv->files[0]->symaddr;
  8849.         iv->decladdr = iv->files[0]->decladdr;
  8850.         iv->symtbl = NewSymTable(iv->category, 0); /* sorted table */
  8851.         combine_syms_decls(iv);
  8852.  
  8853.         realloc_data(iv);
  8854.         reset_data_relocs(iv);
  8855.         reset_text_relocs(iv);
  8856.     }
  8857.     return iv->errors;
  8858. }
  8859.  
  8860. /* ======================== GLOBAL ROUTINES ========================== */
  8861. int
  8862. Global(readfile) (Piv iv, char *infile_name)
  8863. {
  8864. FILE *infile;
  8865. long infile_size;
  8866. char *inbuf;
  8867.  
  8868.     if(!(infile = fopen(infile_name, "rb")))
  8869.     {
  8870.         PERROR(pName ":ERROR: Can't open input file: %s\n", infile_name);
  8871.     }
  8872.     fseek(infile, 0, SEEK_END);
  8873.     infile_size = ftell(infile);    
  8874.     fseek(infile, 0, SEEK_SET);
  8875.  
  8876.     if(infile_size == 0)
  8877.     {
  8878.         PERROR(pName ":ERROR: Empty input file: %s\n", infile_name);
  8879.     }
  8880.     inbuf = Cmalloc(iv->category, infile_size);
  8881.  
  8882.     if(fread(inbuf, 1, infile_size, infile) != infile_size)
  8883.     {
  8884.         fclose(infile);
  8885.         PERROR(pName ":ERROR: reading input file: %s\n", infile_name);
  8886.     }
  8887.     fclose(infile);
  8888.  
  8889.     if(setup_nodelinks(iv, infile_name, inbuf, infile_size))
  8890.         return 4;
  8891.     return 0;
  8892. }
  8893. int
  8894. Global(proc_files) (Piv iv, void *name)
  8895. {
  8896. int ret;
  8897.  
  8898.     if(!(ret = link_files(iv)))
  8899.     {
  8900.         optimize(iv);
  8901.         if(name)
  8902.           iv->symaddr[2] = name;    /* symbol 2 is the output filename */
  8903.  
  8904.         ret = gen_output(iv, iv->symaddr[2]);
  8905.     }
  8906.     return ret;
  8907. }
  8908. void *
  8909. Global(open_instance) (void)
  8910. {
  8911. Piv iv;
  8912. int category;
  8913. #if USING_FRAMEWORK
  8914.     if(num_instance <= 0)
  8915.     {
  8916.         oxlink_clear_bss(pName ".o");    /* reset global storage */
  8917.         local_category = NewMallocCategory();
  8918.     }
  8919.     ++num_instance;
  8920. #endif
  8921.     category = Cnewcat();
  8922.     iv = Ccalloc(category, 1, sizeof(struct _iv));
  8923.     iv->category = category;
  8924.     iv->finextbuf = (PEL)&iv->finextbufstart;
  8925.     return iv;
  8926. }
  8927. void
  8928. Global(close_instance) (Piv iv)
  8929. {
  8930.     if(iv->outfile)
  8931.       fclose(iv->outfile);
  8932.     if(iv->remove_infile)
  8933.     {
  8934.     int i;
  8935.       for(i = 1; i < iv->argc; ++i)
  8936.         unlink(propernameof(iv, iv->argv[i]));
  8937.     }
  8938.     Cfreecat(iv->category);
  8939. #if USING_FRAMEWORK
  8940.     if(--num_instance == 0)
  8941.         freecat(local_category);
  8942. #endif
  8943. }
  8944.  
  8945. /* =========================== THE MAIN PROGRAM ======================= */
  8946.  
  8947. static char *
  8948. filenameof(char *path)
  8949. {
  8950. char *ret = path;
  8951. int i;
  8952.  
  8953.     for(i = 0; path[i]; ++i)
  8954.       if(path[i] == '/')
  8955.         ret = &path[i+1];
  8956.     return ret;
  8957. }
  8958.  
  8959. static char *
  8960. propernameof(Piv iv, char *path)
  8961. {
  8962. char *name = filenameof(path);
  8963. int namlen = strlen(name);
  8964. int i;
  8965.     for(i = namlen-1; i >= 0; --i)
  8966.     {
  8967.       if(name[i] == '/' || name[i] == '\\')
  8968.           break;
  8969.       else if(name[i] == '.')
  8970.         return path;
  8971.     }
  8972.     name = Cmalloc(iv->category, strlen(path)+8);
  8973.     strcpy(name, path);
  8974.     strcat(name, ".anf");
  8975.     return name;
  8976. }
  8977. static void
  8978. Usage()
  8979. {
  8980. fputs(
  8981. "Usage: " pName " [-odsDLR?] [infile...]\n"
  8982. "   -o outfile == name of output file\n"
  8983. "   -d == print debug output\n"
  8984. "   -D == only print debug output\n"
  8985. "   -s == strip declarations and line numbers\n"
  8986. "   -L == generate listing only (to .lst)\n"
  8987. "   -R == remove input file\n"
  8988. "   -? == print this message\n"
  8989. "   Default input file is `code.anf'.\n"
  8990. "   Default output file is specified by the input.\n"
  8991. ,stderr);
  8992. }
  8993.  
  8994. #if USING_FRAMEWORK
  8995. int
  8996. PROG (int argc, char **argv)
  8997. #else
  8998. int
  8999. main (int argc, char **argv)
  9000. #endif
  9001. {
  9002. int i,j;
  9003. char *outfilename = 0;
  9004. volatile Piv iv;
  9005. char debug, only_debug, strip, listing_wanted, remove_infile;
  9006. int ret;
  9007.  
  9008.     remove_infile = listing_wanted = strip = debug = only_debug = 0;
  9009.  
  9010.     /* Get options */
  9011.     for(i = 1; i < argc; ++i)
  9012.     {
  9013.     int trimsize = 1;
  9014.  
  9015.         if(argv[i][0] == '-')
  9016.         {
  9017.             for (j=1; argv[i][j]; j++)
  9018.             {
  9019.                 switch(argv[i][j])
  9020.                 {    
  9021.                     case    'D':
  9022.                         only_debug = 1;
  9023.                         /* FALL THROUGH */
  9024.                     case    'd':
  9025.                         debug = argv[i][++j];
  9026.                         break;
  9027.                     case    's':
  9028.                         strip = 1;
  9029.                         break;
  9030.                     case    'o':
  9031.                         if(argv[i][j+1]) {
  9032.                             outfilename = &argv[i][j+1];
  9033.                         }
  9034.                         else if(i < argc-1) {
  9035.                             outfilename = argv[i+1];
  9036.                             trimsize = 2;
  9037.                         } else {
  9038.                             PWARN(pName ": no output filename\n");
  9039.                             Usage();
  9040.                             return 0;
  9041.                         }
  9042.                         goto trim;
  9043.                         break;
  9044.                     case    'L':
  9045.                         listing_wanted = 1;
  9046.                         break;
  9047.                     case 'R':
  9048.                         remove_infile = 1;
  9049.                         break;
  9050.                     case '?':
  9051.                         Usage();
  9052.                         return 0;
  9053.                     default:
  9054.                         PWARN(pName ": Invalid switch: 0x%x\n", argv[i][j]);
  9055.                         Usage();
  9056.                         return 0;
  9057.                 }
  9058.             }/* END: for(j) */
  9059. trim:
  9060.             /* Trim switch */
  9061.             for(j = i; j < argc-trimsize; ++j)
  9062.                 argv[j] = argv[j+trimsize];
  9063.             argc -= trimsize;
  9064.             --i;
  9065.         }/* END: if('-') */
  9066.     }/* END: for(argc) */
  9067.  
  9068. #if 0
  9069. oxcc_debug(__builtin_iv(),0x40000);
  9070. #endif
  9071.  
  9072.     iv = Global(open_instance) ();
  9073.     if((ret = setjmp(run_env))) {
  9074.         Global(close_instance) (iv);
  9075. #if USING_FRAMEWORK
  9076.         return ret;
  9077. #else
  9078.         exit(ret);
  9079. #endif
  9080.     }
  9081.     iv->debug = debug;
  9082.     iv->only_debug = only_debug;
  9083.     iv->labeltbl = NewSymTable(iv->category, 4092);
  9084. #if REALLY_NEED_OFFSETS
  9085.     iv->newlabeltbl = NewSymTable(iv->category, 4092);
  9086. #endif
  9087.     iv->strip = strip;
  9088.     iv->listing_wanted = listing_wanted;
  9089.     iv->remove_infile = remove_infile;
  9090.     iv->argc = argc;
  9091.     iv->argv = argv;
  9092.  
  9093.     if(argc < 2)
  9094.     {/* Default input filename is 'code.anf' */
  9095.         ret = Global(readfile) (iv, "code.anf");
  9096.     }
  9097.     else
  9098.     {/* READ EACH INPUT FILE */
  9099.         for(i = 1; i < argc; ++i)
  9100.           if((ret = Global(readfile) (iv, propernameof(iv,argv[i]))))
  9101.             break;
  9102.     }
  9103.     if(!ret && !iv->only_debug)
  9104.     {
  9105.         ret = Global(proc_files) (iv, outfilename);
  9106.     }
  9107.     Global(close_instance) (iv);
  9108. #if USING_FRAMEWORK
  9109.     return ret;
  9110. #else
  9111.     exit(ret);
  9112. #endif
  9113. }
  9114.  
  9115.